web: index the feature catalogue and agent documentation

Make the 72 registry capabilities findable in the catalogue and docs search. Derive status, surface badges and documentation links through the existing facts pipeline. Add /features.json, 26 raw Markdown topic routes and /llms-full.txt; align navigation, sitemap and explicit crawler policy. Release JSON-LD uses only stable rows with a declared since version at or before the published install version.

Put the coding-agent category in home metadata and identity across the actual 18 routed locale packs. Correct session receipts, default Auto routing, ACP and read-only MCP server claims; mark Computer Use preview. Document request preview, LSP, execution policy, skills and the reviewed Claude Code import subset. Ratatui component indexing becomes English-only; its hub retains existing locale coverage.

Root gate on base9ebbb063da plus 137 frozen web paths and the separately frozen Q13/X2 native/doc inputs: 1,312 passed; 0 failed; 7 skipped (wrapper101, SDK19, extension host413, security7, Vitest772). Actual receipt lines:
"# pass 413"
"# fail 0"
"# skipped 7"
"Tests  772 passed (772)"

npm ci, facts/latest-release/docs/local GT catalogs, lint, tsc and production build passed. One existing lint warning. Final LLMS-only copy correction: "Tests  3 passed (3)"; fresh production build passed. The existing buildFacts comment was moved back to its owner without an executable change.

Local browser inspection: 36 pages at 375/768/1280 in en/zh/ja/ar, each captured full-page and viewport. All72 feature queries and26 raw Markdown routes passed; every raw topic appears in the full export; zero page errors and no horizontal overflow. The harness disables speculative link prefetch and answers local telemetry with204. This does not establish deployed-site, crawler indexing, WAF or Search Console acceptance. No new tests or code comments; obsolete existing assertions updated. No deployment.
This commit is contained in:
CodeWhale Bot committed 2026-10-12 02:44:25 -07:00
1 parent a2002d0654
commit dd38999ed1
137 files changed
+3247 -413

No files matched your search

+3 -1
View File
@@ -1,7 +1,7 @@
import { Icon } from "@/components/icon";
import { PageHeader, Section } from "@/components/page-header";
import { Status } from "@/components/status-badge";
import { getComputerUse } from "@/lib/i18n/dictionaries";
import { getComputerUse, getFeatures } from "@/lib/i18n/dictionaries";
import { buildPageMetadata } from "@/lib/page-meta";
import { COMPUTER_USE_REPO, getComputerUseRelease } from "@/lib/computer-use-release";
import { getEnv } from "@/lib/kv";
@@ -40,6 +40,8 @@ export default async function ComputerUsePage({ params }: { params: Promise<{ lo
pose="computer"
meta={
<>
<Status tone="attention">{getFeatures(locale).preview}</Status>
<br />
{t.requirements}
<br />
{t.included}
@@ -0,0 +1,14 @@
import { DocArticle } from "../_components/doc-article";
import { getDocsClaudeCode } from "@/lib/i18n/dictionaries";
import { buildPageMetadata } from "@/lib/page-meta";
export async function generateMetadata({ params }: { params: Promise<{ locale: string }> }) {
const { locale } = await params;
const t = getDocsClaudeCode(locale);
return buildPageMetadata({ path: "/docs/claude-code", locale, title: t.metaTitle, description: t.metaDescription });
}
export default async function Page({ params }: { params: Promise<{ locale: string }> }) {
const { locale } = await params;
return <DocArticle t={getDocsClaudeCode(locale)} locale={locale} />;
}
+14
View File
@@ -0,0 +1,14 @@
import { DocArticle } from "../_components/doc-article";
import { getDocsSkills } from "@/lib/i18n/dictionaries";
import { buildPageMetadata } from "@/lib/page-meta";
export async function generateMetadata({ params }: { params: Promise<{ locale: string }> }) {
const { locale } = await params;
const t = getDocsSkills(locale);
return buildPageMetadata({ path: "/docs/skills", locale, title: t.metaTitle, description: t.metaDescription });
}
export default async function Page({ params }: { params: Promise<{ locale: string }> }) {
const { locale } = await params;
return <DocArticle t={getDocsSkills(locale)} locale={locale} />;
}
+5
View File
@@ -33,6 +33,11 @@ export default async function ToolsPage({ params }: { params: Promise<{ locale:
))}
</div>
</section>
<section id="lsp" className="scroll-mt-32">
<h2 className="font-display text-2xl mb-1">{t(TOOLS_COPY.lspTitle)}</h2>
<p className="text-ink-soft mt-3 leading-relaxed">{t(TOOLS_COPY.lspBody)}</p>
<a href="https://github.com/codewhale-hq/CodeWhale/blob/main/docs/LSP_PHP_CUSTOM.md" className="body-link">{t(TOOLS_COPY.lspDocs)}</a>
</section>
<section id="compatibility" className="scroll-mt-32">
<h2 className="font-display text-2xl mb-1">{t(TOOLS_COPY.compatibilityTitle)}</h2>
<p className="text-ink-soft mt-3 leading-relaxed">{t(TOOLS_COPY.compatibility)}</p>
+12 -51
View File
@@ -1,3 +1,4 @@
import { AUTO_ROUTING_COPY } from "@/lib/content/faq-routing";
import Link from "next/link";
import { GETTING_STARTED_STEPS } from "@/lib/content/getting-started";
import { PageHeader } from "@/components/page-header";
@@ -5,7 +6,7 @@ import { FaqSearch } from "@/components/faq-search";
import { buildFaqPageJsonLd } from "@/lib/faq-schema";
import { FACTS } from "@/lib/facts.generated";
import { canonicalLocaleForPath } from "@/lib/i18n/content-locales";
import { getFaq, pickTextLocale } from "@/lib/i18n/dictionaries";
import { getFaq, pickText, pickTextLocale } from "@/lib/i18n/dictionaries";
import { serializeJsonLd } from "@/lib/json-ld";
import { buildPageMetadata } from "@/lib/page-meta";
import { SITE_URL } from "@/lib/page-meta";
@@ -201,21 +202,9 @@ api_key = "sk-or-v1-..."`}
sources: ["docs/MODES.md"],
},
{
q: "What is model auto-routing? What is Fin?",
a: (
<>
<p className="mb-2">
Use <code className="inline">codewhale --model auto</code> or <code className="inline">/model auto</code> to let Codewhale decide how much model power each turn needs.
</p>
<p className="mb-2">
<strong>Fin</strong> is the fast non-thinking path (<code className="inline">deepseek-v4-flash</code> with thinking off) used for routing decisions, summaries, RLM children, context maintenance, and other coordination work. Before the real turn is sent, Fin makes a small routing call to pick the concrete model and thinking level.
</p>
<p>
Short/simple turns can stay on Flash with thinking off. Coding, debugging, release work, architecture, or security review can move up to Pro and/or higher thinking. Fin is local to Codewhale — the upstream API never receives <code className="inline">model: "auto"</code>.
</p>
</>
),
sources: ["README.md", "#1207"],
q: pickText(AUTO_ROUTING_COPY.question, "en"),
a: pickText(AUTO_ROUTING_COPY.answer, "en"),
sources: ["docs/CONFIGURATION.md"],
},
{
q: "What does /goal do?",
@@ -368,16 +357,8 @@ registry = "sparse+https://mirrors.tuna.tsinghua.edu.cn/crates.io-index/"`}
},
{
q: "Why is token consumption so high? / Why is cache hit rate low?",
a: (
<>
Codewhale sends substantial context (system prompt, project instructions, tool definitions) with each turn.
DeepSeek's prefix cache is used aggressively — the system prompt is layered to maximize cache hits.
If you see high token usage, check: are you using <code className="inline">deepseek-v4-pro</code> for simple queries better suited to Flash?
Model auto-routing (Fin) can help pick the right model per turn.
Cache hit rate depends on prompt stability — modifying the system prompt or switching models resets the cache.
</>
),
sources: ["#1177", "#1818", "#743"],
a: pickText(AUTO_ROUTING_COPY.cache, "en"),
sources: ["docs/CONFIGURATION.md"],
},
{
q: "How do I update Codewhale?",
@@ -575,21 +556,9 @@ api_key = "sk-or-v1-..."`}
sources: ["docs/MODES.md"],
},
{
q: "什么是模型自动路由?Fin 是什么?",
a: (
<>
<p className="mb-2">
使用 <code className="inline">codewhale --model auto</code> 或 <code className="inline">/model auto</code> 让 Codewhale 为每个回合自动选择最合适的模型和推理深度。
</p>
<p className="mb-2">
<strong>Fin</strong> 是快速非推理路径(<code className="inline">deepseek-v4-flash</code>,推理关闭),用于路由决策、摘要、RLM 子任务、上下文维护等协调工作。在真实请求发送前,Fin 会做一个小的路由调用来选择具体的模型和推理级别。
</p>
<p>
简短简单的请求可以留在 Flash + 推理关闭的状态。编码、调试、发布工作、架构设计或安全审查则会提升到 Pro 和/或更高的推理级别。Fin 是 Codewhale 本地逻辑——上游 API 永远不会收到 <code className="inline">model: "auto"</code>。
</p>
</>
),
sources: ["README.md", "#1207"],
q: pickText(AUTO_ROUTING_COPY.question, "zh"),
a: pickText(AUTO_ROUTING_COPY.answer, "zh"),
sources: ["docs/CONFIGURATION.md"],
},
{
q: "什么是 Goal 模式?现在可用吗?",
@@ -728,16 +697,8 @@ registry = "sparse+https://mirrors.tuna.tsinghua.edu.cn/crates.io-index/"`}
},
{
q: "为什么 token 消耗这么大?/ 缓存命中率为什么低?",
a: (
<>
Codewhale 每次请求都会发送大量上下文(系统提示、项目说明、工具定义)。
DeepSeek 的前缀缓存被积极使用——系统提示按最稳定的层级排列以最大化缓存命中。
如果你发现 token 使用量很高,请检查:是否在简单查询中使用了 <code className="inline">deepseek-v4-pro</code>(更适合用 Flash)?
模型自动路由(Fin)可以帮助为每个回合选择合适的模型。
缓存命中率取决于提示的稳定性——修改系统提示或切换模型会重置缓存。
</>
),
sources: ["#1177", "#1818", "#743"],
a: pickText(AUTO_ROUTING_COPY.cache, "zh"),
sources: ["docs/CONFIGURATION.md"],
},
{
q: "如何更新 Codewhale?",
+42
View File
@@ -0,0 +1,42 @@
import { PageHeader } from "@/components/page-header";
import { Status, type StatusTone } from "@/components/status-badge";
import { BUILD_FACTS } from "@/lib/facts";
import { FEATURE_CATALOGUE, featureDocsHref, type FeatureStatus, type SurfaceStatus } from "@/lib/features";
import { fill, getFeatures } from "@/lib/i18n/dictionaries";
import { buildPageMetadata } from "@/lib/page-meta";
const TONES: Record<FeatureStatus | SurfaceStatus, StatusTone> = {
stable: "ready", flagged: "attention", experimental: "idle", partial: "attention", preview: "attention", none: "idle",
};
export async function generateMetadata({ params }: { params: Promise<{ locale: string }> }) {
const { locale } = await params;
const t = getFeatures(locale);
return buildPageMetadata({ path: "/features", locale, title: `${t.title} · Codewhale`, description: t.description });
}
export default async function FeaturesPage({ params }: { params: Promise<{ locale: string }> }) {
const { locale } = await params;
const t = getFeatures(locale);
return <>
<PageHeader title={t.title} lede={t.description} actions={<a href="/features.json" className="btn btn-secondary">{t.exportJson}</a>} />
<div className="page-body">
<p className="muted">{fill(t.notice, { count: FEATURE_CATALOGUE.features.length, version: BUILD_FACTS.version ?? "?" })}</p>
<div className="feature-catalogue">
{FEATURE_CATALOGUE.features.map((feature) => <article key={feature.id} id={feature.id} className="feature-entry">
<div lang="en" dir="ltr">
<h2><a href={`#${feature.id}`}>{feature.name}</a></h2>
<p>{feature.summary}</p>
</div>
<div className="feature-states">
<Status tone={TONES[feature.status]}>{t[feature.status]}</Status>
{Object.entries(feature.surfaces).map(([surface, state]) => <Status key={surface} tone={TONES[state]}><bdi>{surface.toUpperCase()}</bdi>: {t[state]}</Status>)}
{feature.flag && <code dir="ltr">{feature.flag}</code>}
{feature.since && <code dir="ltr">v{feature.since}</code>}
</div>
<a className="section-link" href={featureDocsHref(feature)}>{feature.docs ? t.docs : t.source}</a>
</article>)}
</div>
</div>
</>;
}
+4 -3
View File
@@ -10,7 +10,7 @@ import { TerminalCapture } from "@/components/terminal-capture";
import { WhaleLive } from "@/components/whale-live";
import { getFacts } from "@/lib/facts";
import { GETTING_STARTED_STEPS } from "@/lib/content/getting-started";
import { fill, getHome, splitToken } from "@/lib/i18n/dictionaries";
import { fill, getChrome, getHome, splitToken } from "@/lib/i18n/dictionaries";
import {
APP_SIGNUP_URL,
DISCORD_URL,
@@ -134,12 +134,13 @@ export default async function HomePage({ params }: { params: Promise<{ locale: s
className="home-section"
title={d.gainHeading}
scope={d.gainLede}
link={<Link href={`/${locale}/features`} className="section-link">{getChrome(locale).navFeatures}</Link>}
>
<dl className="ruled-list">
{d.gain.map(([name, description]) => (
{d.gain.map(([name, description], index) => (
<div key={name}>
<dt>{name}</dt>
<dd>{description}</dd>
<dd>{description} <Link className="section-link" href={`/${locale}/docs/${["tools", "fleet", "mcp"][index]}`}>{getChrome(locale).navDocs}</Link></dd>
</div>
))}
</dl>
+3 -1
View File
@@ -5,7 +5,7 @@ import { Status, type StatusTone } from "@/components/status-badge";
import { NativeTerminalGallery } from "@/components/native-terminal-gallery";
import { getFacts } from "@/lib/facts";
import { PRODUCT_COPY } from "@/lib/content/product";
import { fill, getHome, pickText } from "@/lib/i18n/dictionaries";
import { fill, getChrome, getHome, pickText } from "@/lib/i18n/dictionaries";
import { buildPageMetadata } from "@/lib/page-meta";
import { getNativeTerminalCopy } from "@/lib/content/native-terminal";
import { TERMINAL_SCREENSHOT } from "@/lib/media-manifest";
@@ -58,6 +58,7 @@ export default async function ProductPage({ params }: { params: Promise<{ locale
<Link href={`/${locale}/docs`} className="btn btn-secondary btn-lg">
{t(PRODUCT_COPY.actions.docs)}
</Link>
<Link href={`/${locale}/features`} className="btn btn-secondary btn-lg">{getChrome(locale).navFeatures}</Link>
</>
}
/>
@@ -92,6 +93,7 @@ export default async function ProductPage({ params }: { params: Promise<{ locale
</span>
<h3>{t(row.title)}</h3>
<p>{fill(t(row.body), { count: providerCount })}</p>
<Link className="section-link" href={`/${locale}/docs/${["tools", "mcp", "fleet"][index]}`}>{getChrome(locale).navDocs}</Link>
</div>
))}
</div>
+1 -1
View File
@@ -34,7 +34,7 @@ const tracksEn: Track[] = [
{ title: "OS command sandbox", note: "Seatbelt on macOS when available; opt-in bubblewrap on Linux when installed. Windows currently reports no OS sandbox." },
{ title: "Durable sessions + tasks", note: "Save, resume, rollback; background task queue with replayable timelines" },
{ title: "Bidirectional MCP", note: "Consume tools from external servers; expose as a server via `codewhale serve --mcp`" },
{ title: "Skills + unified slash palette", note: "Skills load automatically from your Codewhale folder; /help, /mode, /status, /config, /trust, /feedback" },
{ title: "Skills + unified slash palette", note: "Skills load from trusted roots; /help, /mode, /status, /config, /trust, /feedback" },
{ title: "OpenRouter provider", note: "OpenRouter integration with 300+ models across dozens of providers" },
{ title: "OpenAI-compatible & local runtimes", note: "Generic `openai` route for any OpenAI-compatible gateway, plus vLLM, SGLang, and Ollama against your own localhost endpoints — no key required" },
{ title: "Multi-provider support", note: "Hot-swap between providers (DeepSeek, OpenAI, Anthropic, OpenRouter) per session" },
+2 -117
View File
@@ -1,12 +1,12 @@
import Link from "next/link";
import { Icon, type IconName } from "@/components/icon";
import { Icon } from "@/components/icon";
import { PageHeader, Section } from "@/components/page-header";
import { Status } from "@/components/status-badge";
import { getFacts } from "@/lib/facts";
import { getChrome, getRuntime, pickText } from "@/lib/i18n/dictionaries";
import { buildPageMetadata } from "@/lib/page-meta";
const REPO_BLOB_BASE = "https://github.com/codewhale-hq/CodeWhale/blob/main";
import { INTEGRATIONS, TRUST, REPO_BLOB_BASE } from "@/lib/content/runtime-integrations";
export async function generateMetadata({ params }: { params: Promise<{ locale: string }> }) {
const { locale } = await params;
@@ -19,121 +19,6 @@ export async function generateMetadata({ params }: { params: Promise<{ locale: s
});
}
interface Integration {
name: string;
icon: IconName;
experimental?: boolean;
desc: { en: string; zh: string };
href: string;
}
const INTEGRATIONS: Integration[] = [
{
name: "HTTP / SSE Runtime API",
icon: "terminal",
desc: {
en: "Full local HTTP + Server-Sent Events runtime API on 127.0.0.1:7878. Create threads, stream turns, manage background jobs, and control approval decisions — all from any HTTP client or the bundled mobile page.",
zh: "完整的本地 HTTP + Server-Sent Events Runtime API,监听 127.0.0.1:7878。创建线程、流式对话、管理后台任务、控制审批决策——任意 HTTP 客户端或内置手机页面皆可调用。",
},
href: `${REPO_BLOB_BASE}/docs/RUNTIME_API.md`,
},
{
name: "ACP (Agent Client Protocol)",
icon: "plug",
desc: {
en: "Baseline JSON-RPC adapter over stdio for compatible editor clients such as Zed. It supports initialize, new session, prompt, and cancel with text responses; shell and file tools, checkpoint replay, and session loading remain on the full Runtime API.",
zh: "面向 Zed 等兼容编辑器客户端的基础 JSON-RPC stdio 适配器。它支持初始化、新建会话、提示和取消,并返回文本响应;shell 与文件工具、检查点回放和会话加载仍由完整 Runtime API 提供。",
},
href: `${REPO_BLOB_BASE}/docs/RUNTIME_API.md`,
},
{
name: "MCP (Model Context Protocol)",
icon: "plug",
desc: {
en: "Connect Codewhale to external tools and services through configured MCP servers over stdio or HTTP/SSE, or expose Codewhale's own tools to another MCP client.",
zh: "通过已配置的 MCP 服务器(stdio 或 HTTP/SSE)将 Codewhale 连接到外部工具和服务,或把 Codewhale 自身工具暴露给其他 MCP 客户端。",
},
href: `${REPO_BLOB_BASE}/docs/MCP.md`,
},
{
name: "VS Code Extension",
icon: "monitor",
desc: {
en: "Early companion for the local runtime. It can open Codewhale in a terminal, start and check the Runtime API, and show read-only thread summaries and restore points. It does not yet provide full chat, inline edits, or editor actions.",
zh: "本地 Runtime 的早期配套扩展。它可以在终端中打开 Codewhale、启动并检查 Runtime API,以及显示只读线程摘要和还原点;目前尚不提供完整聊天、内联编辑或编辑器操作。",
},
href: "https://github.com/codewhale-hq/CodeWhale/tree/main/extensions/vscode",
},
{
name: "CodeWhale GUI (VS Code)",
icon: "monitor",
desc: {
en: "The community-maintained graphical frontend, in a separate repository: chat, threads, live file changes, and task tracking in a VS Code sidebar over this Runtime API. Install it from the VS Code Marketplace; the source is on GitHub.",
zh: "社区维护的图形前端,位于独立仓库:在 VS Code 侧边栏中基于此 Runtime API 进行对话、管理线程、查看实时文件变更与任务进度。可从 VS Code Marketplace 安装;源码见 GitHub。",
},
href: "https://marketplace.visualstudio.com/items?itemName=HengQuWorld.brotherwhale-vscode",
},
{
name: "Telegram Bridge",
icon: "message",
desc: {
en: "First-party Telegram bot bridge. Start a headless Codewhale session, then chat with it from any Telegram client — approvals, tool results, and completions surface inline.",
zh: "官方 Telegram 机器人桥接。启动无头 Codewhale 会话,在任何 Telegram 客户端中与之对话——审批、工具结果和完成状态内联展示。",
},
href: "https://github.com/codewhale-hq/CodeWhale/tree/main/integrations/telegram-bridge",
},
{
name: "Feishu / Lark Bridge",
icon: "message",
desc: {
en: "First-party Feishu / Lark bot bridge. Chat-native agent loop inside your Feishu workspace with approval messages, session linking, and audit trail.",
zh: "官方飞书 / Lark 机器人桥接。在飞书工作区内实现聊天原生 Agent 循环,支持审批消息、会话关联和审计日志。",
},
href: "https://github.com/codewhale-hq/CodeWhale/tree/main/integrations/feishu-bridge",
},
{
name: "Weixin Bridge",
icon: "message",
experimental: true,
desc: {
en: "Experimental Weixin / WeChat bridge. Receive agent completions and approvals inside WeChat; early-stage and not recommended for production deployments.",
zh: "实验性微信桥接。在微信中接收 Agent 完成通知和审批;早期阶段,不建议用于生产环境。",
},
href: "https://github.com/codewhale-hq/CodeWhale/tree/main/integrations/weixin-bridge",
},
];
const TRUST = [
{
title: { en: "Runs on your machine", zh: "本机运行" },
body: {
en: "The Runtime API binds 127.0.0.1 by default. The local runtime does not require a Codewhale account or hosted relay.",
zh: "Runtime API 默认仅监听 127.0.0.1。本地运行时不需要 Codewhale 账户或托管中继。",
},
},
{
title: { en: "Auth required", zh: "认证必需" },
body: {
en: "Runtime API routes (/v1/*) require a Bearer token. Pass --auth-token at startup or set CODEWHALE_RUNTIME_TOKEN. Only a loopback bind can turn this off, with --insecure-no-auth.",
zh: "Runtime API 路由(/v1/*)需要 Bearer Token。启动时传入 --auth-token,或设置 CODEWHALE_RUNTIME_TOKEN 环境变量。仅在回环地址上可用 --insecure-no-auth 关闭认证。",
},
},
{
title: { en: "Permissions user-controlled", zh: "权限用户控制" },
body: {
en: "Remote clients submit requests and approval decisions through the authenticated Runtime API. Local mode, permission posture, and sandbox policy still apply.",
zh: "远程客户端通过经过认证的 Runtime API 提交请求与审批决定。本地模式、权限姿态和沙箱策略仍然生效。",
},
},
{
title: { en: "Open protocols", zh: "开放协议" },
body: {
en: "The HTTP/SSE Runtime API, MCP surface, and baseline ACP stdio adapter serve different integration needs; choose the interface your compatible client supports.",
zh: "HTTP/SSE Runtime API、MCP 和基础 ACP stdio 适配器分别服务于不同集成场景;请根据客户端需要选择对应接口。",
},
},
];
export default async function RuntimePage({ params }: { params: Promise<{ locale: string }> }) {
const { locale } = await params;
const chrome = getChrome(locale);
+15
View File
@@ -0,0 +1,15 @@
import { AGENT_DOCS, buildTopicMarkdown } from "@/lib/agent-docs";
export const dynamic = "force-static";
export const dynamicParams = false;
export function generateStaticParams() {
return AGENT_DOCS.map((document) => ({ topic: `${document.slug}.md` }));
}
export async function GET(_request: Request, { params }: { params: Promise<{ topic: string }> }) {
const { topic } = await params;
const body = topic.endsWith(".md") ? buildTopicMarkdown(topic.slice(0, -3)) : null;
if (body === null) return new Response("Not found", { status: 404 });
return new Response(body, { headers: { "content-type": "text/markdown; charset=utf-8", "cache-control": "public, max-age=3600" } });
}
+9
View File
@@ -0,0 +1,9 @@
import { FEATURE_CATALOGUE } from "@/lib/features";
export const dynamic = "force-static";
export function GET() {
return Response.json(FEATURE_CATALOGUE, {
headers: { "cache-control": "public, max-age=3600" },
});
}
+9
View File
@@ -0,0 +1,9 @@
import { AGENT_DOCS, buildTopicMarkdown } from "@/lib/agent-docs";
import { buildLlmsTxt } from "@/lib/llms-txt";
export const dynamic = "force-static";
export function GET() {
const body = [buildLlmsTxt(), ...AGENT_DOCS.map((document) => buildTopicMarkdown(document.slug))].join("\n\n");
return new Response(body, { headers: { "content-type": "text/plain; charset=utf-8", "cache-control": "public, max-age=3600" } });
}
+6 -1
View File
@@ -6,7 +6,12 @@ export default function robots(): MetadataRoute.Robots {
rules: [
{
userAgent: "*",
allow: ["/", "/llms.txt"],
allow: ["/", "/llms.txt", "/llms-full.txt", "/features.json", "/docs-markdown/"],
disallow: ["/api/", "/*/admin"],
},
{
userAgent: ["GPTBot", "OAI-SearchBot", "ChatGPT-User", "ClaudeBot", "Claude-SearchBot", "Claude-User", "PerplexityBot", "Perplexity-User", "Google-Extended"],
allow: "/",
disallow: ["/api/", "/*/admin"],
},
],
+1 -1
View File
@@ -5,7 +5,7 @@ import { readCatalogue } from "@/lib/ratatui/catalogue";
// Public, indexable routes (locale-prefixed). /admin and /api are
// intentionally excluded; see app/robots.ts.
const PATHS = ["", "/product", "/install", "/constitution", "/models", "/plugins", "/runtime", "/docs", "/docs/auth", "/docs/computers", "/docs/configuration", "/docs/guide", "/docs/hooks", "/docs/mcp", "/docs/modes", "/docs/review", "/docs/fleet", "/docs/runtime-api", "/docs/sandbox", "/docs/subagents", "/docs/tools", "/docs/troubleshooting", "/docs/trust", "/docs/vocabulary", "/docs/web", "/docs/work", "/docs/pet", "/faq", "/roadmap", "/feed", "/digest", "/changelog", "/contribute", "/community", "/signin", "/signup", "/legal/terms", "/legal/privacy"];
const PATHS = ["", "/product", "/features", "/install", "/constitution", "/models", "/plugins", "/runtime", "/docs", "/docs/auth", "/docs/computers", "/docs/configuration", "/docs/guide", "/docs/hooks", "/docs/mcp", "/docs/modes", "/docs/review", "/docs/fleet", "/docs/runtime-api", "/docs/sandbox", "/docs/subagents", "/docs/tools", "/docs/troubleshooting", "/docs/trust", "/docs/vocabulary", "/docs/web", "/docs/work", "/docs/skills", "/docs/claude-code", "/docs/pet", "/faq", "/roadmap", "/feed", "/digest", "/changelog", "/contribute", "/community", "/signin", "/signup", "/legal/terms", "/legal/privacy"];
export default function sitemap(): MetadataRoute.Sitemap {
const catalogue = readCatalogue();
+5
View File
@@ -182,3 +182,8 @@
.legal-tabs { margin-bottom: var(--space-6); }
.legal-doc > section > h2 { margin-top: var(--space-6); }
.legal-doc .status-line { margin-top: var(--space-7); }
.feature-catalogue { display: grid; gap: 0; margin-block: 1.5rem; }
.feature-entry { padding-block: 1.5rem; border-block-start: 1px solid var(--line); min-width: 0; scroll-margin-top: 6rem; }
.feature-entry h2 { margin-block: 0 0.5rem; }
.feature-entry p { overflow-wrap: anywhere; }
.feature-states { display: flex; flex-wrap: wrap; align-items: center; gap: 0.75rem 1rem; margin-block: 1rem; }
+15 -3
View File
@@ -10,7 +10,9 @@ import {
type DocTopic,
} from "@/lib/docs-map";
import { DOC_TASKS, docTaskHaystack, type DocTask } from "@/lib/docs-tasks";
import { fill, getDocsShell, pickText } from "@/lib/i18n/dictionaries";
import { fill, getDocsShell, getFeatures, pickText } from "@/lib/i18n/dictionaries";
import { FEATURE_CATALOGUE } from "@/lib/features";
import { Status } from "./status-badge";
import { docTopicHaystack, highlightSpan } from "@/lib/search-utils";
import { isSlashShortcut } from "@/lib/slash-shortcut";
import { EmptyState } from "./surface-state";
@@ -135,6 +137,9 @@ export function DocsSearch({ locale }: { locale: string }) {
() => (q ? DOC_TOPICS.filter((_, i) => topicHaystacks[i].includes(q)) : DOC_TOPICS),
[q, topicHaystacks],
);
const filteredFeatures = useMemo(() => q ? FEATURE_CATALOGUE.features.filter((feature) =>
[feature.id, feature.name, feature.summary, feature.flag, feature.docs, ...Object.entries(feature.surfaces).flat()].join(" ").toLowerCase().includes(q)
) : [], [q]);
// Group filtered topics by category (preserve DOC_TOPICS order).
const grouped = useMemo(() => {
@@ -160,8 +165,8 @@ export function DocsSearch({ locale }: { locale: string }) {
return () => window.removeEventListener("keydown", handleKeyDown);
}, [handleKeyDown]);
const total = DOC_TOPICS.length + DOC_TASKS.length;
const matched = filteredTopics.length + filteredTasks.length;
const total = DOC_TOPICS.length + DOC_TASKS.length + FEATURE_CATALOGUE.features.length;
const matched = filteredTopics.length + filteredTasks.length + filteredFeatures.length;
const hasQuery = q.length > 0;
return (
@@ -205,6 +210,13 @@ export function DocsSearch({ locale }: { locale: string }) {
{matched > 0 ? (
<div className="docs-result-groups">
{filteredFeatures.length > 0 && <section className="docs-result-group">
<div className="docs-result-heading"><h2>{getFeatures(locale).title}</h2><span>{filteredFeatures.length}</span></div>
<div className="docs-topic-list">{filteredFeatures.map((feature) => <Link key={feature.id} href={`/${locale}/features#${feature.id}`} className="docs-topic-row">
<div className="docs-topic-main" lang="en" dir="ltr"><div className="docs-topic-title">{highlight(feature.name, query)}</div><p>{highlight(feature.summary, query)}</p></div>
<Status tone={feature.status === "stable" ? "ready" : "attention"}>{getFeatures(locale)[feature.status]}</Status>
</Link>)}</div>
</section>}
{/* Tasks — "I am trying to…" */}
{filteredTasks.length > 0 && (
<section id="tasks" className="docs-result-group docs-task-group">
+418
View File
@@ -0,0 +1,418 @@
[
{
"id": "install",
"slug": "install",
"sources": [
{
"path": "docs/INSTALL.md",
"sha256": "a3898b5b7c4abef90cfc8f9a5eb8d11c7773eac93f3dd6975c86e31621511810",
"content": "# Installing Codewhale\n\n> 阅读简体中文版:[zh_hans/INSTALL.md](zh_hans/INSTALL.md)\n\nCodewhale is an open-source coding agent that runs in your terminal. You give\nit a task (\"fix the failing test\", \"add a CLI flag\"). It reads your repository,\nedits files and runs commands. In the default **Ask** posture it applies file\nedits inside the workspace immediately (and shows you the diff), but asks before\nrunning shell commands, so commit or stash anything you care about first. It\nworks with many model providers. **DeepSeek** is the default.\n\nThe command is `codewhale`. `codew` is a shorter alias for the same program.\n\nThe installation paths were first checked with **v0.10.0** (released 2026-09-22) on a\nfresh **Ubuntu 24.04 x86_64** machine. The dated\n[install receipts](https://github.com/codewhale-hq/Codewhale/blob/37ecdfcc49bc68a9b0d058b97c3946e62c34bd31/docs/install-report/v0.10.0-2026-09-23/RECEIPTS.md) record the commands and output checked at that time. Steps that\ncould not be run on that machine are marked **(untested on this VM: reason)**.\nmacOS, Windows and Android are out of scope, apart from a few notes. A second\npass re-ran the installer, manual-download, archive and npm paths, the no-key\nchecks and zsh completion on **macOS 26.1 (Apple silicon)**; see\n[macOS notes](#macos-notes). Steps that need a model call were not re-run\nthere.\n\nInstall commands that use `latest` resolve to the latest **published** GitHub\nRelease or package. Between releases, `main` may already describe the next\nversion (for example a v0.10.2 source candidate before its tag). A\nprebuilt candidate is available through the official installer only after its\ntag, checksums and release assets exist. Contributors can build `main` now.\n\n## One account for your provider keys\n\n[Register](https://app.codewhale.net/register) or [sign in](https://app.codewhale.net/login)\nto keep your model providers' API keys in one place. Add, replace or remove\nkeys in your account's [Providers settings](https://app.codewhale.net/providers),\nor use the terminal commands below. On another device, sign in and select the\nCodewhale model route to use the same account keys without pasting them again.\n\n```bash\ncodewhale login\ncodewhale account keys set deepseek # asks for the key without echoing it\ncodewhale account keys list # shows status, never the key itself\ncodewhale --provider codewhale # use your account's model route\n```\n\nThe account setup here describes the 0.10.1 source candidate. Signing in does\nnot upload existing local keys. To copy one deliberately, use\n`codewhale account keys set deepseek --from-local`. Account keys stay on the\nservice; they are used for account-routed requests, not downloaded into each\ndevice's local key store. You can keep using local keys or a local model\nwithout an account. See [account key settings](CONFIGURATION.md#account-provider-keys)\nfor updating keys and switching between these options.\n\n## Test and contribute to current source\n\n`latest` selects the latest published release. To test unreleased repairs,\nbuild canonical GitHub `main`, or CNB `main` after verifying its commit matches.\nThe source version number alone does not establish a published package.\n\n```bash\ngit clone --branch main https://github.com/codewhale-hq/CodeWhale.git\ncd CodeWhale\ncargo build --release --locked -p codewhale-cli\ntarget/release/codewhale --version\n```\n\nSee the Cargo section for build prerequisites; use the repository's stable Rust\nselection (declared minimum 1.89). Windows uses `target/release/codewhale.exe`\nand needs MSVC. A development build is separate from a signed release package.\nFor mainland-China downloads and source validation, see [CNB mirror](CNB_MIRROR.md).\nThe [Tencent Lighthouse bootstrap](../scripts/tencent-lighthouse/README.md) is\nbilingual. An npm registry mirror serves the wrapper; native binary downloads\nstill need an available release asset source.\n\n---\n\n## 60-second quickstart (Linux or macOS)\n\n```bash\n# 1. Install. Downloads two checksum-verified binaries into ~/.local/bin (no sudo).\ncurl -fsSL https://codewhale.net/install.sh | sh\n\n# 2. Make sure ~/.local/bin is on your PATH, now and in future terminals.\necho 'export PATH=\"$HOME/.local/bin:$PATH\"' >> ~/.bashrc # zsh: use ~/.zshrc\nexport PATH=\"$HOME/.local/bin:$PATH\"\ncodewhale --version # -> codewhale 0.10.0 (1be1a703b975)\n\n# 3. Give it a DeepSeek API key (from https://platform.deepseek.com/api_keys).\ncodewhale auth set --provider deepseek # prompts for the key; nothing is echoed\ncodewhale auth status --provider deepseek # \"active source: secret store\"\n\n# 4. Run your first task inside a git repository.\ncd ~/your-project\ncodewhale\n```\n\nIn the TUI, type something concrete:\n\n```text\ncreate a Python file primes.py that prints the first 10 primes, run it, and show me the output\n```\n\nCodewhale writes the file, showsLine truncated
}
]
},
{
"id": "guide",
"slug": "guide",
"sources": [
{
"path": "docs/GUIDE.md",
"sha256": "070147fc19193df10e096ff78b32fbb5f775de3f126c0d211c375f50bcd2111e",
"content": "# Codewhale User Guide\n\nThis guide is for your first hour with Codewhale. It explains the main\nworkflow, the important safety controls, and where to go next when you need a\ncomplete reference.\n\nCodewhale has deeper reference documents for installation, configuration,\nproviders, modes, keybindings, tools, and operations. Use this page as a guided\nwalkthrough, then follow the \"Next\" links when you need every option.\n\n## 1. Welcome to Codewhale\n\nCodewhale is a terminal coding agent. You run it from a workspace, give it a\ntask, and it can use structured tools to inspect files, run commands, edit\ncode, and report back with evidence.\n\nThe important difference from a normal chat model is that Codewhale is built\naround a harness:\n\n- It keeps the active workspace and session visible.\n- It routes each turn through explicit modes and approval rules.\n- It shows tool calls in the transcript instead of hiding the work.\n- It can preserve sessions, fork conversations, and continue later.\n- It can run sub-agents for focused background work.\n\nYou can use Codewhale for small questions:\n\n```text\nExplain the authentication flow in this repository.\n```\n\nYou can also use it for multi-step work:\n\n```text\nFind the failing validation path, propose a fix, and wait for my approval\nbefore editing files.\n```\n\nFor a new repository, start conservatively. Ask Codewhale to explore and plan\nbefore asking it to change files. That gives you a reviewable path and makes it\neasier to catch wrong assumptions early.\n\nNext: [ARCHITECTURE.md](ARCHITECTURE.md) explains the internal harness and\nruntime model.\n\n## 2. First Launch\n\nFor a new macOS or Linux installation, use the official GitHub release.\nThe installer verifies the release checksums and provides the same runtime\nunder the `codewhale` and `codew` command names:\n\n```bash\ncurl -fsSL https://codewhale.net/install.sh | sh\n```\n\nWindows users should choose the matching installer or archive from\n[GitHub Releases](https://github.com/codewhale-hq/CodeWhale/releases/latest).\nFor an existing direct install, use `codewhale update --check`, then\n`codewhale update`. npm and Cargo remain secondary packaging routes; Cargo\nalso supports source builds where a compatible prebuilt is unavailable.\nFor occupied directories, package-managed installs, and PATH setup, follow\n[the installation and migration guide](INSTALL.md#recommended-official-github-releases).\nAndroid/Termux uses its own [preview archive or source-build path](INSTALL.md#android--termux-arm64).\n\nDocker is also available when you want an isolated runtime. The published\nimage is currently 0.10.0; to test current `main`, [build it from source](DOCKER.md#building-locally).\n\n```bash\ndocker volume create codewhale-home\ndocker run --rm -it \\\n -e DEEPSEEK_API_KEY=\"$DEEPSEEK_API_KEY\" \\\n -v codewhale-home:/home/codewhale/.codewhale \\\n -v \"$PWD:/workspace\" \\\n -w /workspace \\\n ghcr.io/hmbown/codewhale:latest\n```\n\nOnce the install directory is on PATH, launch Codewhale from the repository or\ndirectory you want it to work in:\n\n```bash\ncodewhale\n```\n\nFor the default GitHub installer destination, you can use\n`\"$HOME/.local/bin/codewhale\"` until that directory is on PATH.\n\nOn first launch, Codewhale opens the composer, even with no key or route.\nWith no key or route, workspace trust is asked once a provider is connected;\notherwise only when the folder requires a decision. A provider is asked for\nwhen you send your first message: the message stays in the box while you sign\nin or use your own key, and a local model is offered only when a local Ollama\nserver answers. The provider step also has an explicit offline route.\n\nEverything optional stays available after that. Use `/setup` for the\nprogressive setup and repair guide, `/settings` for the full typed editor, and\n`/constitution` when you want your own constitution on top of the bundled one.\nThe localized telemetry choice appears only after the workspace is ready and\ndoes not block the composer.\n\nDeepSeek is the default provider. If you want to configure its key before or\nafter the first launch, the most direct setup path is:\n\n```bash\ncodewhale auth set --provider deepseek\n```\n\nYou can also provide a key through the environment:\n\n```bash\nexport DEEPSEEK_API_KEY=\"your-key\"\ncodewhale\n```\n\nNew Codewhale config is stored under `~/.codewhale/config.toml`. Legacy\n`~/.deepseek/config.toml` files are still supported for users migrating from\nthe old name.\n\nUse `/constitution` to review or change standing guidance. After setup, run a\ndoctor check:\n\n```bash\ncodewhale doctor\n```\n\nUse the JSON form when you need a machine-readable report for an issue:\n\n```bash\ncodewhale doctor --json\n```\n\nBoth forms are offline by default. They report structural configuration and\nliteral unknown/not-probed credential states without loading workspace `.env`\ncredentials, openiLine truncated
},
{
"path": "docs/KEYBINDINGS.md",
"sha256": "eff02d51baae0e1f51a55df9c79a7d1571cb3cd809ba6a6fb0d95afa8d9f36d4",
"content": "# Keybindings\n\n> 阅读简体中文版:[zh_hans/KEYBINDINGS.md](zh_hans/KEYBINDINGS.md)\n\nThis is the source-of-truth catalog of every keyboard shortcut the TUI recognizes. Bindings are grouped by **context** — the focus or modal state they fire in. A binding listed under \"Composer\" only takes effect when the composer is focused; one under \"Transcript\" only when the transcript has focus; and so on.\n\nGlobal key chords are not yet user-configurable — tracked for a future release (#436, #437). Hotbar slot actions are configurable with `[[hotbar]]` and `/hotbar`; the Hotbar activation chord remains `Alt-1` through `Alt-8`.\n\n## Global (any context)\n\n| Chord | Action |\n|----------------------|---------------------------------------------------------------|\n| `/help`, `F1` or `Ctrl-/` | Toggle the help overlay. `/help` is what the chrome advertises: it is the one route every terminal delivers, where `F1` is eaten by tmux and some emulators and `Ctrl-/` encoding varies |\n| `F2` | Toggle the typed Settings editor |\n| `F3` | Open the provider/model picker (same as `/provider`) |\n| `Ctrl-K` | Open the command palette (slash-command finder) |\n| `Ctrl-C` | Cancel current turn / dismiss modal / arm-then-confirm quit |\n| `Ctrl-B` | Release the current shell wait so the turn can continue; foreground commands move into `/jobs`, and background tasks keep running. Use `/jobs` or `Bash` with `action: \"wait\"` to inspect output |\n| `Ctrl-D` | Quit (only when the composer is empty) |\n| `Tab` | When the composer is empty, cycle TUI mode: Plan → Work → Operate → Plan |\n| `Shift+Tab` | Cycle permission posture: Ask → Auto-Review → Full Access. Live regardless of composer contents or whether a turn is running (suppressed only while a modal other than Config is open) |\n| `Ctrl-T` | Cycle reasoning effort for the active model. Walks the same ladder as `/model` and `/effort` (catalog or documented route dialect). Always-thinking models omit `off`; Grok 4.6 includes `xhigh`. |\n| `Ctrl-Shift-T` | Toggle live transcript overlay (sticky-tail auto-scroll) |\n| `Ctrl-R` | Open the resume-session picker |\n| `Ctrl-L` | Compact the conversation context (status line shows progress; no-op while a compaction is already running) |\n| `Ctrl-O` | Open the reasoning detail for the selected or current turn, regardless of composer contents |\n| `Ctrl-Alt-O` | Open the whole-turn Turn Inspector, regardless of composer contents |\n| `Alt-V` / `Option-V` (macOS) | Open the details pager for the selected tool/sub-agent card; with nothing selected, the live inspector of the newest running shell, else the visible or most recent card; terminals that emit the legacy Option-V glyph are also handled |\n| `Ctrl-Shift-E` / `Cmd-Shift-E` | Toggle the file tree in the workbar |\n| `Ctrl-]` or `Ctrl-Tab` | Cycle the pet view while the pet main view is showing; otherwise cycle the work dock: TODO → Agents → Jobs → Background. `Ctrl-]` is portable; `Ctrl-Tab` requires the kitty keyboard protocol. Terminal.app uses it to switch terminal tabs |\n| `Ctrl-Shift-Tab` | Cycle the pet view or work dock backwards where the terminal sends the kitty keyboard chord. Terminal.app uses it to switch terminal tabs |\n| `Alt-G` / `Alt-Shift-G` | Scroll transcript to top / bottom when the composer is empty |\n| `Alt-1`-`Alt-8` | Dispatch Hotbar slots 1-8 when no modal or inline picker is open |\n| `Alt-!` / `Alt-@` / `Alt-#` / `Alt-$` | Select the workbar panel: Tasks / Agents / Context / Files |\n| `Ctrl-Alt-0` | Toggle the workbar off / back to the bottom placement |\n| `Alt-L` | Open the pager for the last message (composer empty) |\n| `Alt-P` / `Alt-A` / `Alt-Y` | Jump to Plan / Work, or request Full Access (`Alt-Y` is the legacy permission channel — Work + Full Access — not a separate mode; it honors a locked approval policy) |\n| `Ctrl-X` (Activity workbar) | Cancel all running background shell jobs |\n| `Esc` | Close topmost modal · cancel slash menu · dismiss toast. During a compact that is serving an in-flight turn, Esc stops the turn (the compact is collateral). |\n\n## Composer\n\nEditing the message you're about to send.\n\n| Chord | Action |\n|-----------------------------|---------------------------------------------------------|\n| `Enter` | Send when idle; queue while busy; with an empty composer, send the next queued follow-up now |\n| `Shift-ELine truncated
}
]
},
{
"id": "auth",
"slug": "auth",
"sources": [
{
"path": "docs/CONFIGURATION.md",
"sha256": "3dbae94838073e457a57abd5ec59d1b0ef5be5dc0ae358f515f6e5b6ffe3b23f",
"content": "# Configuration\n\ncodewhale reads configuration from a TOML file plus environment variables.\nAt process startup it may also load literal built-in-provider credentials from\na workspace-local `.env` file. Use the tracked `.env.example` as the template;\ncopy it to `.env`, then add only credential values.\n\nA workspace is not configuration authority. Codewhale therefore ignores\nconfig/profile/home paths, provider/model/base-URL routing, MCP/plugin state,\napproval/sandbox/shell posture, executable paths, runtime settings, and every\nother non-credential `.env` entry. Variable expansion is rejected so a\nrepository cannot substitute an ambient secret into a credential value. Use\n`config.toml`, CLI flags, or values exported by the launching shell for those\nexplicit control-plane settings. `.env` is read from a stable regular-file\nhandle, is capped at 1 MiB, and symbolic links, reparse points, and multiply\nlinked files are rejected.\n\n## Reading and checking configuration from the CLI\n\n`codewhale config get <key>` reads scalar keys, whole tables such as `tools`,\nand nested paths such as `tools.user_input_timeout_seconds`. Displayed tables\nand nested values apply the same recursive credential redaction as `config dump`.\n\n`config set` supports its named scalar keys and the provider, route, and\nnotification commands. It refuses a key that nothing reads and suggests the\nnearest real key (`config set calm_mod on` names `calm_mode`). A settings.toml\nkey such as `calm_mode` or `tool_collapse` is validated and written to the\nuser-global settings.toml, not config.toml; `config get` reads it back from\nthere even when an old config.toml copy (which nothing reads) is still present,\nand names that copy so you can `config unset` it. Settings keys have no project\nscope, so `--project` refuses them. A config.toml key is checked against the\ntype its reader expects and stored as a TOML boolean or number where the\nreader needs one (`yolo = true`, `max_subagents = 4`); `reasoning_effort`\naccepts the same aliases as `/effort` (#6563). Other dotted writes fail before\nmodifying the file and name the TOML table to edit. For example, set a tools\ntimeout in the file as:\n\n```toml\n[tools]\nuser_input_timeout_seconds = 0\n```\n\n`codewhale config doctor` checks credential presence and endpoint shape, and\nwarns about each config.toml root key that nothing reads: a settings.toml key\nleft in config.toml is named as misplaced, and any other unread key gets a\ndid-you-mean. Keys read by any runtime reader are not reported. The warnings do\nnot fail the check, and a clean result does not validate every runtime setting's\nvalue (#6083, #6563).\n\n## Constitution, project instructions, and repo authority\n\nCodewhale has several instruction surfaces. They are deliberately separate so a\npersonal constitution, repo policy, project instructions, and runtime security\ncontrols do not blur together.\n\n- **Bundled global Constitution** — the compiled base law in the binary. It is\n the default floor for every session.\n- **User-global constitution** — the normal guided setup output. Manage it with\n `/constitution` or `/setup`; Codewhale stores structured data at\n `$CODEWHALE_HOME/constitution.json` (default `~/.codewhale/constitution.json`)\n and renders it into a separate `<codewhale_user_constitution>` prose block.\n This can express preferences and stop conditions, but it does not change\n runtime approval policy, sandbox, shell, network, trust, or MCP permissions.\n- **Repo-local constitution** — optional project policy in\n `.codewhale/constitution.json`, described below.\n- **`AGENTS.md`** — cross-agent **project instructions** (prose). This is the\n canonical file for \"how should an agent work in this repo.\" Run `/init` to\n scaffold one. `CLAUDE.md` and `.claude/instructions.md` are read as\n compatibility fallbacks.\n- **Memory and handoffs** — recalled state. Useful, but lower authority than\n constitutions and project instructions.\n\n### Managing the user-global constitution (`/setup` and `/constitution`)\n\nThe bundled **working agreement** is the safe default and no longer adds a\nrequired first-run screen. Customize it later through `/constitution` or the\nprogressive `/setup` guide. Provider/model readiness, workspace trust, and\nruntime posture stay separate from this guidance.\n\nOn the **Working agreement** (constitution) step:\n\n- **`1`–`6`** tune the guided draft. **`G`** previews it, and **`G`** again\n ratifies and saves a fresh structured `constitution.json`.\n- **`A`** (shown only when a provider is configured) asks your first configured\n model to draft the constitution. Drafting is **not** saving: the draft is\n rendered through the same preview and you still press **`G`** to ratify\n before anything persists.\n- **`K`** keeps your existing loaded constitution unchanged (shown only when a\n valid file is already present).\n- **`U`** (or `/coLine truncated
},
{
"path": "docs/CODEWHALE_AGENT.md",
"sha256": "1d10dd28ce67c87eba7cc0fbc6fe8511ed56b93fcc793466ef76269e6cc698ed",
"content": "# Codewhale Agent — one identity, many surfaces\n\n\"Codewhale Agent\" is one product identity with many transport surfaces.\nThis page is the identity map: what each surface is, where each lives, and\nthe rules that keep them one product instead of several.\n\n## The one identity\n\n| Surface | Identity object | Where it lives | State |\n|---|---|---|---|\n| GitHub PR review | GitHub App bot `codewhale-agent[bot]` | GitHub org settings; repo variable `CODEWHALE_APP_ID` + secret `CODEWHALE_APP_PRIVATE_KEY` | `codewhale review --pr N --post` ships with the `codewhale-review.yml` workflow; it no-ops green until the App is configured (founder-gated), then posts as the App instead of the workflow token. Posting is always opt-in via `--post`. |\n| Commit co-author | `.github/AUTHOR_MAP` | repo | existing; harvested co-author credit lands in the contributor graph |\n| Chat channels | per-user bot registration bound to a Codewhale membership | control-plane `services/control-plane/src/integrations/chat/` BotGateway and adapters; contracts in `packages/contracts` | Source includes Telegram and Slack bot pairing and commands. Default read-only command allowlist; opt-in write verbs; approve/deny keyboards route as permission decisions. Availability depends on the deployed gateway and configured bot credentials. |\n\nSlack bot commands control Codewhale; they do not give an agent tools to search\nor read a Slack workspace. The Slack bot requires a user-managed Slack app,\ncredentials and webhook setup. Hosted Slack delivery and a real authenticated\nSlack task have not been qualified, so this source implementation is not a\nready-to-use Slack integration claim. External Slack tools require a separately\nconfigured and authenticated MCP server or API integration.\n\n## Rules that make it one identity\n\n- Every surface is I/O around the single `Engine::run_turn`\n (`crates/tui/src/core/engine/turn_loop.rs`). No surface gets its own\n engine or turn loop.\n- Every surface authenticates to the same Codewhale membership\n (`codewhale login` account session). Membership gates cloud agents;\n provider brands stay internal and invisible.\n- Approvals from any surface route back as permission decisions into the\n same engine. A bare message never executes a gated action.\n- Every command and approval is audited, on every channel.\n- All surfaces are FREE. Rate limits are anti-abuse only. There is no\n per-channel fee, message metering, team gating, or trial timer — and a\n billing hook on a channel feature is forbidden by the money model.\n\n## Naming\n\n- Product: Codewhale. Agent surface: \"Codewhale Agent\".\n- Bot handle wherever it can be chosen: `codewhale-agent`.\n- The agent speaks as \"Codewhale cloud agent\" — never as a provider brand.\n\n## Channel contract\n\nPer-channel command allowlists (default read-only: `status`, `jobs`,\n`receipts`, `help`; opt-in: `new task`, `approve`, `deny`), inline\napprove/deny keyboards routed as permission decisions, `assistant_changes`\nreply mode (message only when something changed), per-channel message\nformat adapters (including Telegram markdown and Slack blocks in source),\nquiet hours + digest, automation output routable\nto any paired channel, one pairing code bound inside the authenticated\napp, unbind revokes instantly.\n\nWeChat note: personal-WeChat automation is **not supported** —\nreverse-engineered protocols get users banned. Official 公众号/服务号 APIs\nare the only acceptable path and are still under assessment.\n\n## Pointer\n\nChannel contracts live in `packages/contracts` (CWC repo); the gateway and\nadapters live in `services/control-plane/src` (CWC repo). The GitHub\nsurface lives in `.github/workflows/codewhale-review.yml` here.\n"
}
]
},
{
"id": "providers",
"slug": "providers",
"sources": [
{
"path": "docs/PROVIDERS.md",
"sha256": "6d578f231ebdb823023bf233f1163026a72ed636e2c377385e1e83e77efc28c6",
"content": "# Provider Registry\n\n> 阅读简体中文版:[zh_hans/PROVIDERS.md](zh_hans/PROVIDERS.md)\n\nSpeech recognition, synthesis, translation and video have separate execution\npaths. See [media models](MEDIA_MODELS.md) for current support and reviewed\nupstream candidates; a chat catalogue row alone does not add a media backend.\n\nThis registry describes provider behavior that is wired into the current\nCodewhale codebase. It is intentionally conservative: shipped entries are\nlimited to provider IDs, config keys, auth paths, base URLs, model resolution,\nand capability metadata that the code already knows about.\n\nDeepSeek remains the default provider, but every entry in `ProviderKind::ALL`\nis a first-class selectable provider route. `ALL` is the catalog/picker\nsurface — one identity per vendor. Dual-wire dialect kinds (`*Anthropic`, e.g.\n`deepseek-anthropic`) and the Model Studio plan variants stay on the enum for\nserde and `provider_for_kind` but are deliberately **not** catalog rows:\na plan is `mode`/`base_url` and a dialect is `wire = openai|anthropic` on the\nprimary provider config (`crates/config/src/provider_kind.rs:221-226`). Hosted\nroutes, generic OpenAI-compatible endpoints, the OpenAI Codex/ChatGPT route,\nnative Anthropic, and local runtimes all run the same terminal harness against\nthe selected provider/model/base URL.\n\nA host reached over plain Chat Completions is an ordinary named provider,\nnot a `ProviderKind`: enum variants are reserved for distinct *wires*\n(Anthropic Messages, Codex Responses, Google thought signatures). Any such\nhost is a `[providers.<name>]` table with a base URL, a model, and a key env\n(`docs/CONFIGURATION.md`); `/provider` and `/setup` keep a \"paste a Base URL\nand a key\" path for exactly this. Offerings come from live `GET /v1/models`\nplus the Codewhale catalog rather than a compiled roster (#5350, #6289).\n\nKnown-good hosts. These ship as bundled descriptor rows in\n`crates/config/assets/provider_descriptors.json` (compiled in by\n`crates/config/src/descriptors.rs`): each row says how to reach the host — wire,\nbase URL, key env, aliases — while model ids stay live from `GET /v1/models`\nand the Codewhale catalog; the example model is only a bootstrap hint. Verify\nagainst the vendor's own docs before trusting any value here:\n\n| Host | Base URL | Example models | API key env |\n| --- | --- | --- | --- |\n| SenseNova | `https://token.sensenova.cn/v1` | `deepseek-v4-flash` | `SENSENOVA_API_KEY` |\n| Baseten | `https://inference.baseten.co/v1` | `deepseek-ai/DeepSeek-V4-Pro` | `BASETEN_API_KEY` |\n| Groq | `https://api.groq.com/openai/v1` | `llama-3.3-70b-versatile` | `GROQ_API_KEY` |\n| Cerebras | `https://api.cerebras.ai/v1` | `llama-3.3-70b` | `CEREBRAS_API_KEY` |\n| Command Code | `https://api.commandcode.ai/provider/v1` | `deepseek/deepseek-v4-flash` | `COMMAND_CODE_API_KEY` |\n| Alibaba Model Studio (DashScope) | `https://dashscope-intl.aliyuncs.com/compatible-mode/v1` | `qwen3.8-flash` | `DASHSCOPE_API_KEY` |\n| AICraft | `https://aicraftapi.com/v1` | `claude-4.6-sonnet`; DeepSeek / Claude / Gemini / Qwen / GLM / MiniMax / Doubao families | `AICRAFT_API_KEY` |\n| Tsubasa | `https://api.tsubasa.sh/v1` | `tsubasa-pro`, `tsubasa-fast` (32,768-token context) | `TSUBASA_API_KEY` |\n| Cheaper Inference | `https://api.cheaperinference.com/v1` | `gpt-5.4-mini`, `claude-sonnet-5`, `gemini-3.1-pro` | `CHEAPER_INFERENCE_API_KEY` |\n| Yolo-Auto | `https://yolo-auto.com/v1` | `qwen3.8-flash`; `yolo` / `yolo-small` | `YOLO_AUTO_API_KEY` |\n\nAICraft's roster spans DeepSeek, Anthropic Claude, Google Gemini, Qwen, GLM,\nMiniMax and Doubao ids on its OpenAI-compatible endpoint. The authority is\n`GET https://aicraftapi.com/v1/models` with your key — pick a model from that\nlist, not from this table.\nTsubasa implements only `GET /v1/models` and Chat Completions. Its two public\nmodel ids share a 32,768-token context, smaller than the 128,000 tokens Codewhale assumes\nfor an unknown model, so set it on the route after saving:\n`codewhale config set providers.tsubasa.context_window 32768`.\n\nCheaper Inference is an OpenAI-compatible gateway with one key for models from\nseveral labs. Model ids are bare, such as `gpt-5.4-mini` or `claude-sonnet-5`.\nPricing varies by model and route; consult the provider’s current catalog.\nThe authority is `GET https://api.cheaperinference.com/v1/models` with your key.\nDocs: <https://cheaperinference.com/docs>.\n\nOpenCode Zen and OpenCode Go are first-class provider routes, configured like\nany other provider below; they are not part of this table. In `/provider`,\ntype to filter the list (letters not bound to a row action); `Ctrl+T` probes the\nselected row's `/models` and records reachability only (a 2xx is not\nmodel-ready).\n\nSources to keep in sync:\n\n- `crates/config/assets/provider_descriptors.json` - built-in and compatible-host\n labels, defaults, aliases, key-env lists, config/secLine truncated
},
{
"path": "docs/MODEL_LAB.md",
"sha256": "e4f26dc6c65008e1ef3df19d6f113ed09399d788cadf7b9189214cb52744c4ef",
"content": "# Model Lab Roadmap\n\nModel Lab is the planned open-model workbench for Codewhale. The north star is\nsimple: Codewhale should make open-source and open-weight models practical in\nterminal coding workflows across every provider that offers them. Model Lab is how\nthose models become discoverable, evaluable, routable, servable, and exportable\nwithout weakening the current terminal-agent contract: local workspace control,\nexplicit provider auth, approval gates, and clear privacy boundaries.\n\nThis document is roadmap language. Some worksets below are roadmap-only.\n\n## Implemented Today\n\n- DeepSeek is the first-class default provider today, with `deepseek-v4-pro`,\n `deepseek-v4-flash`, streaming thinking blocks, Fin routing, `DEEPSEEK_*`\n environment variables, and `~/.deepseek` config compatibility.\n- OpenRouter, Novita, Fireworks, NVIDIA NIM, AtlasCloud, Wanjie Ark, Hugging\n Face Inference Providers, generic OpenAI-compatible endpoints, SGLang, vLLM,\n and Ollama are supported provider paths where their IDs appear in\n `/provider`, `codewhale --provider`, or `codewhale models`.\n- Hugging Face Inference Providers are available through the\n OpenAI-compatible router at `https://router.huggingface.co/v1`. Select the\n route with `huggingface`, `hugging-face`, `hugging_face`, or `hf`; configure\n `HUGGINGFACE_API_KEY` or `HF_TOKEN` for auth.\n- Model auto-routing chooses a concrete DeepSeek model and thinking level per\n turn. It is not a TUI mode.\n- Fin is the fast `deepseek-v4-flash` thinking-off path for routing,\n summaries, cheap checks, RLM child calls, wakeup verification, and\n binary-completion checks.\n- Self-hosted OpenAI-compatible endpoints can be used through SGLang, vLLM,\n Ollama, or the generic `openai` provider configuration.\n\n## Still Planned\n\n- A native Hugging Face Hub browser, model passport picker, or direct Hub search\n workflow. The OpenAI-compatible Hugging Face Inference Providers route is\n implemented separately as a chat provider.\n- Built-in Hugging Face model card, dataset, adapter, safetensors, Spaces, or\n Jobs workflows.\n- Native Unsloth, NeMo, or Arcee integrations.\n- A dedicated Model Lab UI tab.\n- Built-in eval leaderboards, hosted observability, or training-infrastructure\n orchestration.\n\nUntil those land, use the provider paths above, MCP servers, or external\nworkflows explicitly configured by the user.\n\n## Model Lab Principle\n\nModel Lab should help users answer practical questions:\n\n- Which model should handle this turn?\n- Which open or open-weight model can I run locally or through a trusted\n provider?\n- Which provider offers this model with the latency, price, context window,\n license, and privacy posture I need?\n- What did this model cost, how did it perform, and what data left my machine?\n- Can I reproduce, export, or self-host the route?\n\nIt should never hide provider boundaries, silently upload local artifacts, or\ndescribe a model as available before Codewhale can actually route to it.\n\n## Hugging Face Workset\n\nImplemented today:\n\n- Hugging Face Inference Providers as an explicit OpenAI-compatible router\n provider, selected with `huggingface`, `hugging-face`, `hugging_face`, or\n `hf`.\n- Model IDs are sent to the router exactly as selected, including\n org-prefixed Hugging Face model IDs.\n\nPlanned scope:\n\n- Hub API auth and model discovery.\n- Model cards, licenses, tags, safetensors metadata, adapters, and dataset\n links surfaced in a terminal-friendly way.\n- Native Hub browser and model-passport metadata on top of the already separate\n Hugging Face Inference Providers chat route.\n- Hugging Face Jobs as an optional remote execution path for user-approved\n experiments.\n\nNon-goal for now: claiming native Hub search, model passports, Spaces/Jobs, or\nModel Lab UI exists before those surfaces are implemented in code.\nThe inference-provider API key does not imply Hub browsing/export, upload, or\nJobs authorization.\n\n## Unsloth Workset\n\nPlanned scope:\n\n- Fine-tuning recipes and adapter workflows for users who already own the data\n and compute path.\n- Export guidance that keeps dataset, adapter, and checkpoint locations explicit.\n- Compatibility notes for models that can return to local serving or a hosted\n OpenAI-compatible endpoint.\n\n## NeMo Workset\n\nPlanned scope:\n\n- Training and alignment workflow notes for users operating NVIDIA-centric\n infrastructure.\n- Clear boundaries between NVIDIA NIM inference support that exists today and\n future NeMo training or customization workflows.\n\n## Arcee Workset\n\nPlanned scope:\n\n- Small-model routing and specialization experiments.\n- Exportable routes that make it clear when a task is handled by a smaller\n model, Fin, or full DeepSeek reasoning.\n\n## Serving Workset\n\nPlanned scope:\n\n- Better local and private serving ergonomics for SGLang, vLLM, Ollama, and\n OpenAI-compatible gateways.\n- HLine truncated
}
]
},
{
"id": "configuration",
"slug": "configuration",
"sources": [
{
"path": "docs/CONFIGURATION.md",
"sha256": "3dbae94838073e457a57abd5ec59d1b0ef5be5dc0ae358f515f6e5b6ffe3b23f",
"content": "# Configuration\n\ncodewhale reads configuration from a TOML file plus environment variables.\nAt process startup it may also load literal built-in-provider credentials from\na workspace-local `.env` file. Use the tracked `.env.example` as the template;\ncopy it to `.env`, then add only credential values.\n\nA workspace is not configuration authority. Codewhale therefore ignores\nconfig/profile/home paths, provider/model/base-URL routing, MCP/plugin state,\napproval/sandbox/shell posture, executable paths, runtime settings, and every\nother non-credential `.env` entry. Variable expansion is rejected so a\nrepository cannot substitute an ambient secret into a credential value. Use\n`config.toml`, CLI flags, or values exported by the launching shell for those\nexplicit control-plane settings. `.env` is read from a stable regular-file\nhandle, is capped at 1 MiB, and symbolic links, reparse points, and multiply\nlinked files are rejected.\n\n## Reading and checking configuration from the CLI\n\n`codewhale config get <key>` reads scalar keys, whole tables such as `tools`,\nand nested paths such as `tools.user_input_timeout_seconds`. Displayed tables\nand nested values apply the same recursive credential redaction as `config dump`.\n\n`config set` supports its named scalar keys and the provider, route, and\nnotification commands. It refuses a key that nothing reads and suggests the\nnearest real key (`config set calm_mod on` names `calm_mode`). A settings.toml\nkey such as `calm_mode` or `tool_collapse` is validated and written to the\nuser-global settings.toml, not config.toml; `config get` reads it back from\nthere even when an old config.toml copy (which nothing reads) is still present,\nand names that copy so you can `config unset` it. Settings keys have no project\nscope, so `--project` refuses them. A config.toml key is checked against the\ntype its reader expects and stored as a TOML boolean or number where the\nreader needs one (`yolo = true`, `max_subagents = 4`); `reasoning_effort`\naccepts the same aliases as `/effort` (#6563). Other dotted writes fail before\nmodifying the file and name the TOML table to edit. For example, set a tools\ntimeout in the file as:\n\n```toml\n[tools]\nuser_input_timeout_seconds = 0\n```\n\n`codewhale config doctor` checks credential presence and endpoint shape, and\nwarns about each config.toml root key that nothing reads: a settings.toml key\nleft in config.toml is named as misplaced, and any other unread key gets a\ndid-you-mean. Keys read by any runtime reader are not reported. The warnings do\nnot fail the check, and a clean result does not validate every runtime setting's\nvalue (#6083, #6563).\n\n## Constitution, project instructions, and repo authority\n\nCodewhale has several instruction surfaces. They are deliberately separate so a\npersonal constitution, repo policy, project instructions, and runtime security\ncontrols do not blur together.\n\n- **Bundled global Constitution** — the compiled base law in the binary. It is\n the default floor for every session.\n- **User-global constitution** — the normal guided setup output. Manage it with\n `/constitution` or `/setup`; Codewhale stores structured data at\n `$CODEWHALE_HOME/constitution.json` (default `~/.codewhale/constitution.json`)\n and renders it into a separate `<codewhale_user_constitution>` prose block.\n This can express preferences and stop conditions, but it does not change\n runtime approval policy, sandbox, shell, network, trust, or MCP permissions.\n- **Repo-local constitution** — optional project policy in\n `.codewhale/constitution.json`, described below.\n- **`AGENTS.md`** — cross-agent **project instructions** (prose). This is the\n canonical file for \"how should an agent work in this repo.\" Run `/init` to\n scaffold one. `CLAUDE.md` and `.claude/instructions.md` are read as\n compatibility fallbacks.\n- **Memory and handoffs** — recalled state. Useful, but lower authority than\n constitutions and project instructions.\n\n### Managing the user-global constitution (`/setup` and `/constitution`)\n\nThe bundled **working agreement** is the safe default and no longer adds a\nrequired first-run screen. Customize it later through `/constitution` or the\nprogressive `/setup` guide. Provider/model readiness, workspace trust, and\nruntime posture stay separate from this guidance.\n\nOn the **Working agreement** (constitution) step:\n\n- **`1`–`6`** tune the guided draft. **`G`** previews it, and **`G`** again\n ratifies and saves a fresh structured `constitution.json`.\n- **`A`** (shown only when a provider is configured) asks your first configured\n model to draft the constitution. Drafting is **not** saving: the draft is\n rendered through the same preview and you still press **`G`** to ratify\n before anything persists.\n- **`K`** keeps your existing loaded constitution unchanged (shown only when a\n valid file is already present).\n- **`U`** (or `/coLine truncated
},
{
"path": "docs/LEGACY_PATHS.md",
"sha256": "89f7a556479d57911d9589af582c13a0c7494418d9d47f430d1bfa6c74ad3333",
"content": "# Legacy `.deepseek/` compatibility paths — audit & migration status (#3068)\n\n> 阅读简体中文版:[zh_hans/LEGACY_PATHS.md](zh_hans/LEGACY_PATHS.md)。\n\n## v0.9.10 cleanse ledger\n\nThis is the release-window decision record for residue that can otherwise look\ninterchangeable in a text search. A compatibility entry must name the contract\nthat still requires it; new production code must use a current path.\n\n| Class | Surface | Decision / contract |\n|---|---|---|\n| DELETE | Retired underwater build-version test override | Removed in `1cc4d1d1b`; the owner test was already deleted and the production-only build version remains authoritative. |\n| MIGRATE | Cross-task Agent Mail | `bd998495a` and managed-app `4ff7bc50d` replace guessed event aliases and same-session mailbox conflation with one durable typed runtime protocol. |\n| MIGRATE | TUI `status_message` writes | Active residue; touched flows must move to the typed toast/current-state owner. No new writes are allowed. |\n| COMPATIBILITY | `.deepseek/` state and stored provider aliases | Read fallback for upgraded installations and stored provider identity; writes remain Codewhale-only. Details are below. |\n| COMPATIBILITY | `agent_message` transcript/protocol decoding | Persisted transcripts and tool wire values require decoding; it is not the cross-task Agent Mail transport. |\n| COMPATIBILITY | Managed runtime envelope schema 1 | Previously persisted/enrolled runner replay; current local Codewhale Agent Mail producer is schema 2 and both normalize to the managed envelope. |\n| CURRENT | DeepSeek provider support | A real selectable provider, not product branding; provider-scoped names and configuration remain. |\n| CURRENT | Same-session subagent mailbox | Start/status/peek/message/followup/interrupt/wait/cancel stays scoped to a parent runtime session. |\n| CURRENT | Web locale dictionaries | The application and documentation routes have no page-local `isZh` branches; new copy continues through dictionaries. |\n| CURRENT | Safety, authorization, protocol, persistence, migration, and data-integrity tests | These protect external or durable contracts and are not copy/layout cleanup candidates. |\n\nSnapshot on 2026-08-19: `10,954` Rust `#[test]` attributes under\n`crates/tui`, `523` TUI `status_message` source lines, and zero page-local\n`isZh` files under `apps/web/app` in the paired managed-app candidate. Counts\nare inventory signals, not deletion targets.\n\nCodewhale was renamed from DeepSeek-TUI. To avoid breaking existing installs, the runtime reads\nstate from the new `~/.codewhale/` location but **falls back** to the legacy `~/.deepseek/` location,\nand always **writes** to `~/.codewhale/`. This doc audits each legacy reference and records a\nkeep / deprecate / remove decision so the migration is auditable.\n\n## The canonical resolver (use this for new code)\n\nState-dir resolution is consolidated in `crates/config/src/lib.rs`:\n\n| Symbol | Line | Purpose |\n|---|---|---|\n| `CODEWHALE_APP_DIR` / `LEGACY_APP_DIR` | 5369 | re-exported from `crates/paths` (defined at `crates/paths/src/lib.rs` 13 / 16) |\n| `codewhale_home()` | 5375 | `~/.codewhale` |\n| `legacy_deepseek_home()` | 5392 | `~/.deepseek` (legacy) |\n| `resolve_state_dir(subdir)` | 5434 | **read** path: `~/.codewhale/<subdir>`, falling back to `~/.deepseek/<subdir>` when only the legacy dir exists |\n| `ensure_state_dir(subdir)` | 5458 | **write** path: always creates under `~/.codewhale/<subdir>` |\n\nMigration contract: read-with-fallback, write-to-new. This preserves the v0.8.44 migration for\nusers who still have `~/.deepseek/` while steering all new writes to `~/.codewhale/`.\n\n## Per-path decisions\n\n**Decision for all legacy references below: keep-as-fallback.** Removing the `.deepseek` fallback\nwould strand users who upgraded in place and never re-ran onboarding. Revisit only after a release\nthat actively migrates `~/.deepseek/` → `~/.codewhale/` on first run and a deprecation window.\n\n| Reference | Routed through `resolve_state_dir`? | Decision |\n|---|---|---|\n| `config::resolve_state_dir` / `ensure_state_dir` | n/a (the resolver itself) | keep — canonical |\n| `crates/tui/src/skills/mod.rs` (`~/.deepseek/skills`) | no — hardcoded | keep-as-fallback; route through resolver in a follow-up refactor |\n| `crates/tui/src/prompts.rs` (`LEGACY_HANDOFF_RELATIVE_PATH = \".deepseek/handoff.md\"`) | no — explicit legacy const | keep — explicit legacy handoff fallback |\n| `crates/tui/src/workspace_trust.rs` | no — hardcoded | keep-as-fallback; follow-up |\n| `crates/tui/src/session_manager.rs` | no — hardcoded | keep-as-fallback; follow-up |\n| `crates/runtime/src/skill_state.rs` | no — hardcoded | keep-as-fallback; follow-up |\n| `crates/tui/src/tools/skill.rs` | no — hardcoded | keep-as-fallback; follow-up |\n| `crates/tui/src/snapshot/mod.rs` | no — hardcoded | keep-as-fallback; follow-up |\n| `crates/runtime/src/woLine truncated
}
]
},
{
"id": "modes",
"slug": "modes",
"sources": [
{
"path": "docs/MODES.md",
"sha256": "7026b81d483cfaf911f6467f2ef318c7eb51dd84bc8c0aaf0788f3e53138269d",
"content": "# Modes and Permission Postures\n\n> 阅读简体中文版:[zh_hans/MODES.md](zh_hans/MODES.md)\n\nCodewhale has three related concepts:\n\n- **TUI mode**: what kind of visible interaction you're in (Plan/Work/Operate).\n- **Permission posture**: how aggressively the UI asks before executing tools.\n- **Workflow**: named steps that coordinate sub-agents, with dependencies and\n results, available in any TUI mode.\n\nModel selection is separate. `--model auto` and `/model auto` route each turn to\na concrete model and thinking level; they are not TUI modes and are not part of\nthe `Tab` cycle.\n\nWorkflow runs named steps through the same sub-agent runtime; Fleet manages\ntheir saved roles and model assignments. A workflow adds ordering, result\nhandoffs, gates and a progress view. The active mode and permission posture\nstill control what each step may execute.\n\nBefore assigning steps, query `agent(action=\"roster\")` for the saved Fleet\nmodels and roles. A plan child can select a listed model with `model`, or use\nthe saved `role`/`profile` assignment. An Exact Fleet fixes each member's route.\n\n## TUI Modes\n\nPress `Tab` to complete composer menus or cycle through the visible modes\nwhen the composer is empty: **Plan → Work → Operate → Plan**. `Tab` never sends\nor queues composer text; use `Enter` to send or queue it.\nPress `Shift+Tab` to cycle permission posture (Ask → Auto-Review → Full Access).\nEvery change of effective permission writes a `Permissions changed to …` line\nin the transcript.\nPress `Ctrl+T` to cycle reasoning effort.\nRun `/mode` to open the mode picker, or switch directly with `/mode work`,\n`/mode plan`, or `/mode operate`.\n\n- **Plan**: design-first prompting. The stable primitive names remain familiar, but the runtime centrally refuses file mutation and shell execution. Read-only inspection and policy-allowed research, including deferred Web search/fetch, remain available. When a Plan turn successfully finishes a nonempty response, including a prose-only plan, the TUI asks how to continue: Work (Ask), Work (Auto-Review), or keep planning. Work sends the exact approved response as a normal follow-up and preserves that turn's existing To-dos, or adds one pending plan item without replacing unrelated work.\n- **Work** (internally `agent`): ordinary multi-step execution. The first-turn toolbox includes `read`, `write`, `edit`, `bash`, `agent`, `workflow`, and `todo_write`, plus `create_goal`, `get_goal`, and `update_goal` so goal controls are available without discovery. The agent calls `create_goal` when a request is a durable objective; the host never infers a goal from wording, and the contract must not tell the model otherwise. Approval, sandbox, repository law, and managed policy decide what may execute.\n- **Operate**: Work at full strength, the \"ultra\" mode. Same tools and authority as Work; the difference is how they are used. Each substantive request becomes a goal (`create_goal`), the plan stays visible (`todo_write`), multi-part work runs through `workflow` and parallel `agent` workers, non-trivial changes get an independent reviewer before they are called done, long commands keep running in the background, and recurring or watch-type work is offered as an `automation` (created after approval). It keeps going until the goal is verified, blocked on you, or paused.\n\n`Act` and `/mode act` remain compatibility aliases for Work. Saved settings\nstill normalize to the internal value `agent`.\n\n### Tool availability by mode\n\n| Tool family | Plan | Work | Operate |\n|:---|:---:|:---:|:---:|\n| `read` and policy-allowed deferred research tools | yes | yes | yes |\n| `write` and `edit` | visible names; execution denied | approval- and policy-gated | same as Work |\n| `bash` | visible name; execution denied | approval- and policy-gated | same as Work; delegation is preferred when parallelism or isolation helps |\n| `agent` | yes, subject to child-depth authority | yes, subject to child-depth authority | yes, subject to child-depth authority |\n| Deferred native, MCP, and plugin tools | discoverable through `tool_search` when policy permits | same | same |\n| Paid or external-service tools | follows permission posture | follows permission posture | follows permission posture |\n| Access outside the workspace root | explicit trusted paths only | only through trusted paths or trust mode | same trusted-path/trust policy as Work; fleet profiles never widen it |\n\nOperate changes scheduling emphasis, not authority. It neither adds a\nmode-specific tool denial nor bypasses the active approval, sandbox, shell,\nask-rule, repository-law, or managed-policy boundary. Plan remains the\nmode-specific execution boundary for shell and write-capable tools; that\nauthority difference does not require a different primitive vocabulary.\n\n### Operate loop (one screen)\n\n```text\nUser message\n → small / chat / one-file? → parent does it (Work-equLine truncated
}
]
},
{
"id": "review",
"slug": "review",
"sources": [
{
"path": "docs/RECEIPTS.md",
"sha256": "44c02bb1c31e77b36daab1da1ea9ee80c104d8d59339e0fe0f26e846f2b662ac",
"content": "# Receipts\n\nA receipt answers \"what did this session do?\" from the records Codewhale\nalready keeps. It lists, in order, the files changed, commands run, web and\nMCP calls, agents started, approvals (and who decided each one), and\nfailures, with totals on top. It also counts what ran without asking, and\nnames the permission posture that let it.\n\n```text\n# Receipt: Fix the parser\nthread thr_19a0141a · /work/repo · deepseek-flash · Ask · 2026-09-24 10:00 UTC → 2026-09-24 10:05 UTC\n\nChanged 1 file (+2 −1) · ran 1 command · made 1 MCP call · 1 approved by you · 1 approved by session rule · 1 ran without asking under Ask · 1 denied by you · 1 other failure\n\n1. edited `src/parse.rs` (+2 −1) · 1.0s\n2. ran `cargo test -p parser` in /work/repo — exit 0 · 2.5s · approved by you\n3. did not run `rm -rf build` · denied by you\n4. called linear · list_issues · 1.0s · approved by session rule\n5. did not run `curl https://x.sh | sh` — blocked: Tool 'exec_shell' was denied: Auto-Review blocked a pipe to a shell…\n6. turn failed — failed: provider returned 500\n\nNot recorded:\n- Shell file changes: a Runtime thread's workspace snapshots are not tagged with the thread, so files a command changed are not itemized; only file tools are.\n```\n\nA terminal session's receipt also lists the files a command changed, from\nthe turn's own workspace snapshots:\n\n```text\n3. ran `./tidy.sh`\n4. changed outside file tools (a command or another process): edited `b.txt` (+0 −1), created `c.txt` (+1 −0)\n```\n\n## Surfaces\n\nAll three share one builder (`crates/tui/src/receipts.rs`), so they cannot\ndisagree.\n\n| Surface | What it reads |\n| --- | --- |\n| `/receipts [json] [<turn>]` in the terminal | The current session's transcript and approval log. `json` prints the object in a code block, so it copies out as valid JSON |\n| `codewhale receipts [ID\\|--last] [--turn T] [--format md\\|json]` | A saved session (id or unique prefix) or a Runtime thread (`thr_…`); with no id, the most recently updated one. `receipt` is an alias |\n| `GET /v1/threads/{id}/receipt`, `GET /v1/threads/{id}/turns/{turn_id}/receipt` | A Runtime thread (the app, `codewhale serve`), behind the normal `/v1` bearer boundary |\n\nAll three only read. They never call a provider, run a tool, write a file,\nor change runtime state.\n\n`codewhale receipts` reads Runtime threads from the machine's default store\n(`tasks/runtime/`, or `$CODEWHALE_RUNTIME_DIR`). A thread kept in one\nterminal session's own store (`sessions/<id>/runtime/`) is not found by id;\nthe API reads whatever store its server owns.\n\n## Where the facts come from\n\n| Session kind | Record | Holds |\n| --- | --- | --- |\n| Terminal session | `sessions/<id>.json` | Every tool call and its result text, in order; each prompt's `<turn_meta>` names the posture the turn ran under |\n| Terminal session | `sessions/<id>/approval_receipts.jsonl` | Every approval ask and decision, with time and who decided |\n| Runtime thread | `tasks/runtime/turns`, `items` | Every tool call with its input, status, start and end time, and structured result (exit code, diff, agent status); each turn's `permission_posture` |\n| Runtime thread | `tasks/runtime/events/<thread>.jsonl` | `approval.required` / `approval.decided`, with the flags that say who decided |\n\n### Who decided an approval\n\n| Receipt says | Meaning | Recorded as |\n| --- | --- | --- |\n| approved by you / denied by you | A person answered: the terminal card, the app, the web mirror, or an API client acting for them | `decided_by: \"user\"`; Runtime event with no `auto` flag |\n| … by session rule | A remembered \"for this session\" rule answered | `decided_by: \"session_rule\"`; Runtime event with `auto` and a `grant_id` |\n| … by posture | The mode or permission posture answered without a prompt | `decided_by: \"posture\"`; Runtime event with `auto` or `posture` |\n| approval timed out | The card expired unanswered | outcome `timeout` |\n| turn stopped while waiting / nobody could be asked | Codewhale could not ask anyone: the turn had ended or stopped, or the request never reached a person. Counted as not answered, never as a denial, even where the record says `denied` | `decided_by: \"host\"` |\n| approved / denied, with no \"by\" | A record written before 0.10.1, or a sub-agent's request. The totals say \"(decider not recorded)\" | no `decided_by` |\n\nThe totals line counts approvals and denials separately, by who gave them:\n`1 approved by you · 1 denied by you` is two decisions.\n\n### Ran without asking\n\nMost calls never produce an approval. Under Full Access nothing asks; under\nAsk, reads and allowed tools run without a prompt, and a remembered rule can\nskip one. Those calls leave no approval record, so the receipt counts them\ninstead: `ran_without_asking` is every file change, command, code run, web\nor MCP call, and agent start that ran with no approval on reLine truncated
},
{
"path": "docs/CONFIGURATION.md",
"sha256": "3dbae94838073e457a57abd5ec59d1b0ef5be5dc0ae358f515f6e5b6ffe3b23f",
"content": "# Configuration\n\ncodewhale reads configuration from a TOML file plus environment variables.\nAt process startup it may also load literal built-in-provider credentials from\na workspace-local `.env` file. Use the tracked `.env.example` as the template;\ncopy it to `.env`, then add only credential values.\n\nA workspace is not configuration authority. Codewhale therefore ignores\nconfig/profile/home paths, provider/model/base-URL routing, MCP/plugin state,\napproval/sandbox/shell posture, executable paths, runtime settings, and every\nother non-credential `.env` entry. Variable expansion is rejected so a\nrepository cannot substitute an ambient secret into a credential value. Use\n`config.toml`, CLI flags, or values exported by the launching shell for those\nexplicit control-plane settings. `.env` is read from a stable regular-file\nhandle, is capped at 1 MiB, and symbolic links, reparse points, and multiply\nlinked files are rejected.\n\n## Reading and checking configuration from the CLI\n\n`codewhale config get <key>` reads scalar keys, whole tables such as `tools`,\nand nested paths such as `tools.user_input_timeout_seconds`. Displayed tables\nand nested values apply the same recursive credential redaction as `config dump`.\n\n`config set` supports its named scalar keys and the provider, route, and\nnotification commands. It refuses a key that nothing reads and suggests the\nnearest real key (`config set calm_mod on` names `calm_mode`). A settings.toml\nkey such as `calm_mode` or `tool_collapse` is validated and written to the\nuser-global settings.toml, not config.toml; `config get` reads it back from\nthere even when an old config.toml copy (which nothing reads) is still present,\nand names that copy so you can `config unset` it. Settings keys have no project\nscope, so `--project` refuses them. A config.toml key is checked against the\ntype its reader expects and stored as a TOML boolean or number where the\nreader needs one (`yolo = true`, `max_subagents = 4`); `reasoning_effort`\naccepts the same aliases as `/effort` (#6563). Other dotted writes fail before\nmodifying the file and name the TOML table to edit. For example, set a tools\ntimeout in the file as:\n\n```toml\n[tools]\nuser_input_timeout_seconds = 0\n```\n\n`codewhale config doctor` checks credential presence and endpoint shape, and\nwarns about each config.toml root key that nothing reads: a settings.toml key\nleft in config.toml is named as misplaced, and any other unread key gets a\ndid-you-mean. Keys read by any runtime reader are not reported. The warnings do\nnot fail the check, and a clean result does not validate every runtime setting's\nvalue (#6083, #6563).\n\n## Constitution, project instructions, and repo authority\n\nCodewhale has several instruction surfaces. They are deliberately separate so a\npersonal constitution, repo policy, project instructions, and runtime security\ncontrols do not blur together.\n\n- **Bundled global Constitution** — the compiled base law in the binary. It is\n the default floor for every session.\n- **User-global constitution** — the normal guided setup output. Manage it with\n `/constitution` or `/setup`; Codewhale stores structured data at\n `$CODEWHALE_HOME/constitution.json` (default `~/.codewhale/constitution.json`)\n and renders it into a separate `<codewhale_user_constitution>` prose block.\n This can express preferences and stop conditions, but it does not change\n runtime approval policy, sandbox, shell, network, trust, or MCP permissions.\n- **Repo-local constitution** — optional project policy in\n `.codewhale/constitution.json`, described below.\n- **`AGENTS.md`** — cross-agent **project instructions** (prose). This is the\n canonical file for \"how should an agent work in this repo.\" Run `/init` to\n scaffold one. `CLAUDE.md` and `.claude/instructions.md` are read as\n compatibility fallbacks.\n- **Memory and handoffs** — recalled state. Useful, but lower authority than\n constitutions and project instructions.\n\n### Managing the user-global constitution (`/setup` and `/constitution`)\n\nThe bundled **working agreement** is the safe default and no longer adds a\nrequired first-run screen. Customize it later through `/constitution` or the\nprogressive `/setup` guide. Provider/model readiness, workspace trust, and\nruntime posture stay separate from this guidance.\n\nOn the **Working agreement** (constitution) step:\n\n- **`1`–`6`** tune the guided draft. **`G`** previews it, and **`G`** again\n ratifies and saves a fresh structured `constitution.json`.\n- **`A`** (shown only when a provider is configured) asks your first configured\n model to draft the constitution. Drafting is **not** saving: the draft is\n rendered through the same preview and you still press **`G`** to ratify\n before anything persists.\n- **`K`** keeps your existing loaded constitution unchanged (shown only when a\n valid file is already present).\n- **`U`** (or `/coLine truncated
}
]
},
{
"id": "work",
"slug": "work",
"sources": [
{
"path": "docs/TOOL_SURFACE.md",
"sha256": "ecfb9e76e13225dabd3313b89c40c8bc904beb8be1d88e370151df72a90bc61a",
"content": "# Tool surface\n\n> 阅读简体中文版:[zh_hans/TOOL_SURFACE.md](zh_hans/TOOL_SURFACE.md)。\n\nThis document describes the current model-facing tool contract. The v0.9.1\ncutover that produced it is recorded in `docs/RUNTIME_SIMPLIFICATION_DESIGN.md`;\nread the workspace version from `Cargo.toml`, not from this line. The registry\nremains larger than the first-turn catalog so\nsaved transcripts can replay and uncommon capabilities can be loaded on demand.\nThe model should learn one canonical name for each common operation.\n\nImplementation sources:\n\n- `crates/tui/src/core/engine/tool_catalog.rs` owns the eager/deferred catalog.\n- `crates/tui/src/tools/registry.rs` registers canonical tools and hidden aliases.\n- `crates/tui/src/tools/{file,file_tool,shell}.rs` own the small foreground\n primitive behavior and schemas; the other native tools remain searchable.\n- `docs/RUNTIME_SIMPLIFICATION_DESIGN.md` records the v0.9.1 cutover and receipt.\n\n## Default-active contract\n\nNew turns start with twelve eager native names plus synthetic `tool_search`:\n\n1. `read`\n2. `write`\n3. `edit`\n4. `file_search`\n5. `bash`\n6. `agent`\n7. `workflow`\n8. `todo_write`\n9. `create_goal`\n10. `get_goal`\n11. `update_goal`\n12. `load_skill`\n13. `tool_search` (synthetic, always active)\n\nThe twelve native names are `DEFAULT_ACTIVE_NATIVE_TOOLS` in\n`crates/tui/src/core/engine/tool_catalog.rs`, pinned by\n`default_active_contract_keeps_discovery_and_core_tools_eager`. An authority\nboundary may remove `agent` at the maximum child depth, but route size alone\nmust not change this core vocabulary.\n\nThe direct schemas deliberately stay small:\n\n| Tool | Input | Purpose |\n|---|---|---|\n| `read` | `path`, optional `offset`, optional `limit` | Read a bounded file window with explicit continuation or truncation notices. |\n| `write` | `path`, `content` | Create or replace a file. |\n| `edit` | `path`, `edits` | Apply one or more unambiguous text replacements against one original snapshot. |\n| `bash` | `command`, optional `timeout`, optional `description` | Run one cancellable foreground shell command and return a bounded tail. The optional description is display-only. |\n| `agent` | delegated task and optional scope/context controls | Start or inspect focused child work. |\n| `workflow` | plan/script/source_path plus run controls | Coordinate multi-agent phases with dependencies and completion checks. |\n| `todo_write` | complete replacement list of `{content, status}` items | Keep optional, agent-owned progress notes for genuinely multi-step work. |\n| `create_goal` | objective plus optional budget | Start the session goal the turn works toward. |\n| `get_goal` | none | Read the active goal and its progress. |\n| `update_goal` | terminal status | Mark the goal complete or blocked. |\n| `tool_search` | `query`, optional matching controls | Discover policy-allowed deferred tools and add selected schemas to this conversation's toolbox. |\n\nMode is an authority decision, not a synonym system. Plan, Work, and Operate\nuse the same primitive identities. Plan centrally refuses `write`, `edit`, and\n`bash`; Work and Operate still pass those calls through approval, sandbox,\ntrusted-path, repository-law, and managed-policy gates. Full Access changes\nordinary approval behavior but does not bypass hard safety or repository law.\n\n`update_plan` remains registered only for saved-artifact compatibility and is\nnot model-visible. `tasks`, `Git`, `Run`, `Web`, `remember`, and other\nspecialized capabilities are searchable rather than first-turn ceremony.\n\nA Bash description appears as a muted, bounded note under the command on the\nTUI shell card, including on automatic runs. It never replaces the command and\nis excluded from execution, exact approval keys and Auto-Review input. The\noriginal description remains in the recorded tool input and exports. Approval\nprompts, `/jobs`, the activity inspector, ACP and other Runtime clients keep\nshowing the command; this change adds no description row to those surfaces.\n\n## Local code execution\n\n`code_execution` (Python) and `js_execution` (Node.js) use the same\npermission-aware local launcher as workspace task gates and test runs. Ordinary\napproval retains the effective session policy. To retry a denied exact call\nwith wider permissions, supply `sandbox_permissions` (`workspace-write` or\n`danger-full-access`) and a nonempty `justification`; Ask mode requires explicit\none-shot user approval. The approved policy affects only that call.\n\nBoth tools read source from stdin, return stdout/stderr/return_code, and keep\nthe existing timeout and process-tree cleanup. They are not persistent REPLs;\ntracebacks refer to stdin rather than a temporary script path. The separate\nRLM/REPL kernel is not changed by this launcher integration.\n\nPlatform/backend limits of the shared launcher still apply: no available local\nwrapper means workspace-write remains unLine truncated
},
{
"path": "docs/TOOL_LIFECYCLE.md",
"sha256": "bfb222f258d585410471033e7c9c0c2b18b2570d489bd9806b3af101ddc2bb62",
"content": "# Historical Tool-Surface Lifecycle Policy (v0.8.53)\n\n> 阅读简体中文版:[zh_hans/TOOL_LIFECYCLE.md](zh_hans/TOOL_LIFECYCLE.md)\n\n**Status:** Historical design record, not current runtime documentation. The\nv0.9.1 canonical action surface and replay-only alias contract are documented in\n[`RUNTIME_SIMPLIFICATION_DESIGN.md`](RUNTIME_SIMPLIFICATION_DESIGN.md) and\n[`TOOL_SURFACE.md`](TOOL_SURFACE.md). No catalog code landed in this old cycle — the code\nwork is **deferred**. This document is the umbrella policy for GitHub **#2681**,\nwith **#2682** and **#2683** as concrete instances of the planned diet. It\ndescribes *what will be done* and the invariants any future diet PR must hold.\n\n**Scope of related open work (do not contradict):**\n- PR **#2684** — subagent role vocabulary, lifecycle signals, eval ergonomics.\n Legacy subagent-name cleanup + guardrail tests in this policy rebase on #2684.\n- PR **#2685** — git-history active + RLM/field errors.\n\n**What actually happened, so you can read the rest as history:** the \"hidden\ncompatibility\" plan below was *not* what shipped in full. `exec_wait` and\n`exec_interact` were removed rather than kept dispatchable. The work-progress\nsurface is different: `todo_write` is the sole model-visible name, while\n`work_update`, `TodoWrite`, `todo`, `checklist_write`, and `checklist_update`\nstay registered as hidden-compatibility aliases of `TodoWriteTool` so old\ntranscripts replay; `checklist_add`, `checklist_list`, `todo_add`,\n`todo_update`, and `todo_list` are not registered and are not callable.\n`tts`/`speech` remain dispatchable. See [`TOOL_SURFACE.md`](TOOL_SURFACE.md)\nfor the shipped contract. Read §4 and §8 as a rejected catalog-diet proposal,\nnot as a guarantee that every listed alias is gone.\n\n**All file:line citations here were correct at v0.8.52/0.8.53 and are now\nexpired.** They have not been rewritten, because renumbering a historical\nrecord makes it look current. Symbols this document cites that no longer exist\nat all include `ARCEE_FIRST_TURN_NATIVE_TOOLS` and `apply_provider_tool_policy`\n(both removed by `1bfcced43c`, \"fix(engine): remove Arcee tool catalog\nexception\"), and the planned `HIDDEN_COMPATIBILITY_TOOLS` / `DEPRECATED_ALIASES`\nsets, which were never written. Resolve any symbol here against the tree before\nacting on it.\n\n---\n\n## 1. Purpose and the weaker-model problem\n\nCodewhale ships a large native tool surface. The first-turn *active* partition\nof that surface is what every model sees before it has run a single\n`tool_search_*` call. Today that active set contains several **near-duplicate\ntools** that map to the *same* implementation under different names:\n\n- `exec_wait` and `exec_shell_wait` are both `ShellWaitTool`\n (`crates/tui/src/tools/registry.rs:526,529`).\n- `exec_interact` and `exec_shell_interact` are both `ShellInteractTool`\n (`registry.rs:527,530`).\n- `tts` and `speech` are both `SpeechTool`\n (`registry.rs:787-792`, both deferred).\n- `todo_write` is the single model-visible `TodoWriteTool` surface;\n `todo_write`, `TodoWrite`, `todo`, `checklist_write`, and\n `checklist_update` are hidden compat aliases of it.\n\nFor a strong model, redundant names are harmless noise. For **weaker / smaller\nmodels** (the Arcee Trinity lane, `deepseek-v4-flash` child executors, and any\nnon-thinking executor), every additional near-duplicate in the visible set is a\nreal cost:\n\n- It widens the choice space with options that do *nothing distinct*, increasing\n wrong-tool selection and oscillation between synonyms.\n- It spends scarce first-turn catalog budget (Section 5) on zero-information\n entries.\n- It dilutes the \"one name = one thing\" contract that lets a small model reason\n about the surface at all.\n\nThe lifecycle policy exists to **shrink and discipline the model-visible\nsurface** without ever breaking the ability to replay an old transcript that\nreferenced a now-retired name.\n\n### Canonical work-tracking surface for v0.9.1\n\nThe model-visible progress surface is a single tool: `todo_write` (#4132).\nAgents and Fleet workers use it for concrete To-do / Work progress under the\nactive runtime thread or durable task.\n\n`task_*` and the Fleet/Workflow ledger remain the durable lifecycle owners.\nChecklist metadata is the model-visible projection of progress:\n`task_updates.checklist` carries the current items, completion percentage, and\nin-progress item.\n\n**The To-do is the only Work surface.** `update_plan` is conversational\nreasoning — strategy, context, and route notes for complex initiatives. It is\nnot a progress surface, must not duplicate To-do items, and plan-only state is\nnever rendered as a To-do snapshot.\n\n**No request re-states the list.** The model learns what is on the To-do the way\nit learns anything else: from its own `todo_write` call, whose input is the\nwhole list, and the short receipt it returned (counts and the itLine truncated
}
]
},
{
"id": "pet",
"slug": "pet",
"sources": [
{
"path": "docs/PET_MODE.md",
"sha256": "45d222acf2f7878912637ebfeb553dac8ce34c9521d8b56442cd882f91a3406a",
"content": "# Pet mode\n\n> 阅读简体中文版:[zh_hans/PET_MODE.md](zh_hans/PET_MODE.md)\n\nPet mode turns the terminal you already use into a glanceable status view. A\nwhale fills the main view and shows what the session is doing: idle, working,\nwaiting for you, done, or failed. The message box stays at the bottom, so you\ncan keep typing. Replies and agents are one key away.\n\nEach terminal runs its own pet mode for its own session. With several terminals\nopen, you can look across them and see which one needs you, which is still\nworking, and which has finished.\n\n```text\nCodewhale ● working\n (the whale)\n ●\nF5 replies & agents · /pet off standard view\nCtrl+] view: whale\n╭──────────────────────────────────────────────────────────╮\n│❯ Type a follow-up… │\n╰──────────────────────────────────────────────────────────╯\n ● auto Shift+Tab to change work (Tab) 2 agents\n```\n\n## Turn it on\n\n```text\n/pet on # pet mode becomes the main view\n/pet off # back to the standard view\n/pet # toggle\n/pet status # on or off, whether the habitat is open, and companion identity\n```\n\n`/pet on` and `/pet off` are saved as the `pet_mode` setting (also in the\nsettings editor), so a new session starts the way you left it. Pet mode never\nstarts a turn, calls a model, or changes your draft, mode, or approvals; it only\npresents the session you are already running.\n\n## What the whale tells you\n\nThe first line of the view and the mark under the whale always carry the state\nas a mark and a word, so it reads without colour or motion:\n\n| State | Mark and word | Meaning |\n| --- | --- | --- |\n| Ready | `○ idle` | Nothing running. |\n| Working | `● working` | A turn is running, including tools and verification. |\n| Needs you | waiting or approval phase | The session is waiting for an approval or an answer. Motion is reduced while it waits. |\n| Done | `✓ Done` | The last turn completed. |\n| Failed | `✕ failed` | The last turn ended in failure. |\n\nThe status bar underneath keeps its usual live readouts, such as the agent\ncount (`2 agents`) and the work bar. Transient notices, such as a retry\n(`Retry attempt: transport 1/3; network error; waiting 0.94s`), show on the\nsecond line.\n\n## Views\n\n`Ctrl+]` switches the pet to its next view while the pet main view is showing.\nTerminals with the kitty keyboard protocol can also send `Ctrl+Tab` for the\nnext view and `Ctrl+Shift+Tab` for the previous view. Terminal.app uses those\nTab chords to switch terminal tabs; use `Ctrl+]` there. The\nfooter's second line names the current view, `Ctrl+] view: whale`, and\nclicking it also moves to the next view. `/pet avatar <key>` jumps straight to\none.\n\n| View | What it draws | When its requirement is missing |\n| --- | --- | --- |\n| `whale` | The companion's live dot whale. | Shows `cove` (or `braille`) until the companion is reachable (`codewhale pet serve`) and this terminal's session is its source (`/pet source`). |\n| `cove` | The local half-block whale, without the translucent cove scenery. | Needs colour: `braille` is shown under `NO_COLOR`, a 16-colour terminal, or an unknown background. `COLORTERM=truecolor` enables true colour; `CODEWHALE_APPEARANCE=dark` or `light` selects a known background. |\n| `braille` | The local whale in coloured Braille dots. | Shows only the state words under `CODEWHALE_ASCII_SAFE` or when the art area is smaller than 16x8 cells. |\n| `pixels` | The companion's whale as a kitty-graphics image. | Needs kitty graphics, synchronized output, a known cell size in pixels, and `CODEWHALE_PET_GRAPHICS` not set to `braille`; otherwise shows `particles`. Terminal.app has no kitty graphics. |\n| `particles` | The companion's Braille particle grid. | Shows the resting whale and `offline` while the companion is unreachable. |\n| `whale-girl` | The bundled sprite avatar. | Needs colour, as `cove` does; otherwise shows a one-ink ASCII form. |\n| Installed avatar packs | Each pack, in catalog order. | Shows `particles` while the pack's atlas loads. |\n\nThe order is `whale → cove → braille → pixels → particles → whale-girl →`\ninstalled packs, then back to `whale`. A view that cannot draw is never\nskipped: it shows its fallback, and the line under the title says what is\nmissing, for example `pixels needs kitty graphics · showing particles`.\n\n## Replies and agents on demand\n\nThe main view stays quiet. Press `F5`, or run `/pet inspect`, to open the\ninspector over it:\n\n- the whale and an **Agents** list on top, with each agent's state and usage;\n- a **Reply** pane below, which stLine truncated
}
]
},
{
"id": "subagents",
"slug": "subagents",
"sources": [
{
"path": "docs/SUBAGENTS.md",
"sha256": "a251947eb5e4c2b73fcfc68f1df764ac0604d135601fa44501f66a60cf5f4353",
"content": "# Fleet and sub-agents\n\n> 阅读简体中文版:[zh_hans/SUBAGENTS.md](zh_hans/SUBAGENTS.md)\n\nFleet manages saved models and role assignments for these same sub-agents.\nUse `agent` for an individual assignment and `workflow` for phases with\ndependencies and completion checks. See [Workflow authoring](WORKFLOW_AUTHORING.md)\nfor plans that use the Fleet model shortlist.\n\nFleet roles are the user-facing vocabulary for delegated work: a parent\nlaunches a focused `general`, `explore`, `planner`, `reviewer`, `implement`,\n`test`, or `advisor` through `agent` and gets back an `agent_id`, declared\ndeliverables, and effective limits while the worker runs. The default receipt is\ncompact; request addressed detail when you need the transcript handle or ledger.\nThe internal runtime type is `FleetRole` (formerly\n`SubAgentType`); the older role spellings (`worker`, `scout`, `plan`,\n`review`, `builder`, `verifier`, `consultant`, `oracle`, …) remain accepted only as a persisted/deserialize\ncompatibility adapter during v0.9.x. New prompts and config should use fleet\nnames.\n\nChild assignments run through the same `Engine::run_turn` planner, executor,\nSession and approval inbox as ordinary turns. The private captured ChildGrant\nnarrows tool actions, shell, workspace, network and descendant depth at the final\nexecution boundary. The existing SubAgentManager still owns launch slots,\ncoordination, worker checkpoints and terminal delivery; it does not run another\nmodel/tool loop. Work and the single bounded reporting turn share that configured\nchild Engine and its original deadline.\n\nTransient provider failures use Core's dispatch and retry boundaries. An exhausted\nbudget or interrupted request preserves the recorded checkpoint and a continuation\nhandle. Each actually dispatched attempt carries its original session, route and\nsource identity: provider usage is billed once, then projected to the worker\nledger. A successful response without usage and an unknown request outcome retain\ndistinct coverage gaps; neither is priced as zero. For work that must survive\nprocess restarts, sleep or remote execution, use Fleet or a Workflow-backed run.\n\nSub-agents inherit the parent's permitted tool registry, including `agent`\ncoordination. Spawning obeys one absolute depth ceiling: the root is depth 0,\nits child is depth 1, and a child at `max_spawn_depth` cannot spawn again.\nThe operator default is 3, with a hard ceiling of 8. A role, saved profile, or\ncompatibility request can only narrow that ceiling. Recovery and transcript\nforking retain the source's position and bounds; they do not buy another\ngeneration. The removed `agent_open`/`agent_eval`/`agent_close` lifecycle tools\nare absent from every registry.\n\nHealthy children continue after an ordinary parent response. Their completion\nreturns through the existing Engine inbox and can wake the parent for another\nnormal turn. Explicit interruption or cancellation remains authoritative.\n`detached: true` additionally opts a subtree out of parent-turn cancellation;\nit does not remove child budgets or the headless host's deadline.\n\nThis doc covers roles and individual worker controls. Use `workflow` to coordinate\nmultiple assignments through the same worker runtime; see the per-role prompts in\n`crates/tui/src/tools/subagent/mod.rs` (`*_AGENT_INTRO`) and the in-line\ntool description.\n\n## Role taxonomy\n\nThe `type` field on `agent` selects a fleet posture for the child\n(`agent_type` is accepted as a compatibility alias). Each role is a distinct\nstance toward the work — not just a different label.\n\n## Maintainer posture\n\nSub-agents help Codewhale move faster, but the parent agent still owns the\nmaintainer decision. Use children to gather evidence, review patches, and run\nverification while keeping the community posture in\n[`AGENT_ETHOS.md`](AGENT_ETHOS.md): issues are open intake, PR gates are\nreview-load controls, and harvested work needs clear contributor credit.\n\nWhen a child reviews community work, the parent should still inspect the PR\ndiff, linked issues, tests, and CI before merging, harvesting, closing, or\ndeferring it. A sub-agent's result is a working set, not a substitute for\nstewardship.\n\n| Role | Stance | Writes? | Network? | Shell posture | Typical use |\n|---------------|----------------------------------------|---------|----------|---------------|----------------------------------------------|\n| `general` | flexible; do whatever the parent says | yes | yes | yes | the default; multi-step tasks |\n| `explore` | read-only; map the relevant code fast | no | yes | bounded inspection | \"find every call site of `Foo`; check the PR with gh\" |\n| `planner` | analyse and produce a strategy | no | yes | read-only probes | \"design the migration; dLine truncated
}
]
},
{
"id": "fleet",
"slug": "fleet",
"sources": [
{
"path": "docs/FLEET.md",
"sha256": "134c6a358522c6367a8f004813daab56150a371e9433811236524fb2978ea0cf",
"content": "# Agent fleet\n\n> Baca terjemahan bahasa Indonesia: [id/FLEET.md](id/FLEET.md)\n\nAgent fleet is the local-first roster and member-selection layer for durable\nmulti-worker runs. It does not execute or authorize work. After fleet resolves\nwho should participate, the delegated coordinator launches a headless\n`codewhale exec` run and the Runtime tracks it durably. See\n[AGENT_RUNTIME.md](AGENT_RUNTIME.md) for how sub-agents, `exec`, and\nfleet-backed workers converge on one runtime. In product language, a user may\nstill \"open a sub-agent\"; in architecture language, durable nested work uses a\nfleet member identity with delegated runtime execution.\n\n## Naming and compatibility boundary\n\n**Fleet** is the public product noun. The durable ledger, saved rosters, config\ntables, and `--fleet` flag share that name:\n\n| Surface | Canonical |\n| --- | --- |\n| CLI | `codewhale fleet …` |\n| Slash command | `/fleet …` |\n\nThese shared names are load-bearing wherever changing them would break\nexisting workspaces, receipts, or scripts:\n\n- the durable ledger `.codewhale/fleet.jsonl` and the log directories\n `.codewhale/fleet/` and `.codewhale/fleet-host/`;\n- saved rosters `fleets/<name>.toml` and their `schema = \"fleet\"` header, under\n `$CODEWHALE_HOME/` or the workspace's `.codewhale/` (checked-in rosters at the\n workspace root's `fleets/` are still read);\n- the `[fleet]` config table (inline `[fleets.*]` tables were removed in 0.9.14; named fleets live in `fleets/<name>.toml` files);\n- the `codewhale workflow run --fleet <name>` flag;\n- wire, receipt, and control-plane operation ids such as `fleet.status`.\n\nThe rest of this document uses fleet as the public product noun and retains\nthese literal paths, keys, flags, and ids.\n\nUse a fleet roster rather than anonymous short-lived `agent` fanout whenever a\ndelegated run needs stable member identities across retries, sleep/restart,\nremote execution, receipts, or a ledgered audit trail. The initial CLI surface\nis:\n\nFor a guided start-to-monitor walkthrough that combines fleet task specs with\nWorkflow authoring, see [fleet + Workflow Tutorial](FLEET_WORKFLOW_TUTORIAL.md).\n\n```sh\ncodewhale fleet init\ncodewhale fleet run tasks.json --check # validate only; nothing is created or launched\ncodewhale fleet run tasks.json --max-workers 4\ncodewhale fleet status\ncodewhale fleet inspect <worker-id>\ncodewhale fleet logs <worker-id>\ncodewhale fleet artifacts <worker-id>\ncodewhale fleet interrupt <worker-id>\ncodewhale fleet restart <worker-id>\ncodewhale fleet resume <run-id>\ncodewhale fleet stop --all\n```\n\n`codewhale fleet resume <run-id>` is the restart-recovery verb: it replays the\nledger, reconciles any in-flight lease whose worker stopped heartbeating\n(retrying within the task's budget, else failing and escalating per the alert\npolicy), and prints the post-resume status. It launches no new work and is\nidempotent, so it is safe to run after a manager exit, laptop sleep, or runtime\nrestart.\n\nCoordinator state for fleet-backed runs is stored under the workspace in\n`.codewhale/fleet.jsonl`. Worker logs and adapter logs are stored under\n`.codewhale/fleet/` and `.codewhale/fleet-host/`.\n\n## Public contract: identity, membership, and selection\n\n**Fleet** = the user's model inventory: who is in the roster and which member is selected.\n\nA public fleet identity consists only of:\n\n- a stable member id and an optional user-facing name;\n- a semantic role, such as `explore`, `implement`, or `reviewer` (the legacy\n spellings `worker`, `scout`, `builder`, `verifier`, `consultant`, and `oracle`\n are still accepted on input and map to `general`, `explore`, `implement`,\n `test`, and `advisor`);\n- an exact provider/model identity, or an explicit inherited route;\n- visible roster state or origin.\n\nProject or workspace trust, filesystem and network reach, secret access,\napproval mode, sandboxing, tool authorization, and every other form of runtime\nauthority are separate delegated-coordination and Runtime policy inputs. They\nare never fleet identity fields, and they never select or reroute a fleet\nmember. The Runtime applies and clamps those policies only after member\nselection; if the selected member cannot run inside the effective envelope,\nlaunch fails closed instead of choosing somebody else.\n\nNatural-language member selection is deterministic. A caller may name:\n\n- an exact member id, optionally as `member:<id>` or `id:<id>`;\n- a unique user-facing member name, optionally as `name:<name>`;\n- a unique semantic role, for example `explore` or `role:explore`;\n- an exact pinned model id, for example `deepseek-v4-flash`, or its offline\n display name, for example `DeepSeek V4 Flash`; or\n- an exact `route:<provider>/<model>`.\n\nAn unqualified exact member id wins. Every other match succeeds only when it\nidentifies one distinct roster member. Multiple matches produce an ambiguity\nerror Line truncated
},
{
"path": "docs/WORKFLOW_AUTHORING.md",
"sha256": "a1e76bf73acb1ce04de81b6677550a9fb9af4a137b1ffbad0cd274d01cd14a4e",
"content": "# Workflow Authoring\n\n> 阅读简体中文版:[zh_hans/WORKFLOW_AUTHORING.md](zh_hans/WORKFLOW_AUTHORING.md)。\n\n> **Ordinary multi-agent work does not require this file.** In Operate, send\n> normal messages. Small work stays direct; multiple delegated steps use a\n> compact Workflow plan with dependencies, bounded scopes, and completion\n> evidence. Fleet manages the same sub-agents and roles. One bounded,\n> independent task can use a direct agent, with `followup` for continued work.\n> Act/Agent may also use optional soft-auto launch. See\n> [Automatic Workflows](AUTOMATIC_WORKFLOWS.md).\n\nWorkflow has one runtime boundary: authored source lowers to typed\nRust `WorkflowSpec`, Rust validates the IR, and the scheduler/headless worker\nruntime executes leaves. Authoring languages do not get hidden authority to own\nfiles, shell, network, providers, cancellation, or TUI state.\n\nCompatibility launch paths on the `workflow` tool:\n\n| Input | When to use |\n|-------|-------------|\n| `plan` | Structured goal / phases / children (preferred agent path) |\n| `script` | Short inline JS the model owns |\n| `source_path` | Checked-in `.workflow.js` / `.workflow.ts` in the workspace |\n\nUse `agent(action=\"roster\")` to inspect the saved Fleet models and roles before\nassigning children. Native plan children accept `model` for a saved shortlist\nselector, or `role`/`profile` for a saved assignment. Named Exact Fleets keep\ntheir member routes fixed and reject per-step model overrides. Plan children\nalso accept `cwd`, a repository-relative working directory — required in\nmulti-repository workspaces so the child (and worktree isolation) resolves the\nright repository, mirroring `task({cwd})`.\n\nFor a guided walkthrough from fleet task specs to Workflow authoring and\nmonitoring, see [fleet + Workflow Tutorial](FLEET_WORKFLOW_TUTORIAL.md).\n\n\n## Access model\n\nThe Workflow script is a **coordinator only**. It has no filesystem or shell of\nits own. Real work happens in sub-agents the script launches.\n\n| Layer | What it can access |\n|-------|--------------------|\n| Workflow script (JS VM) | Script variables, branching/loops, `task()` / `parallel()` / `pipeline()`, `phase` / `log`, `budget` / `args`. **No** direct FS, shell, network, env, imports, clock, or randomness. |\n| Workflow-spawned sub-agents | Normal tool surface (read/search/edit/write, shell, web, MCP) subject to role posture, allowlists, and parent policy. File edits for write-capable roles auto-accept under Workflow; shell / web / MCP still require parent auto-approve or fail closed. |\n| Parent session | Working directory, configured tools/MCP, permission mode, sandbox/network rules. |\n\n### Scale\n\n- Up to **16 concurrent** live agents in one run (additional spawns wait for a slot).\n- Up to **1_000 agents per run** (VM lifetime spawn cap).\n- Configured `max_children` and `max_concurrent` can narrow these limits.\n- Automatic launch is model-judged on scope; the host enforces only the hard `max_children` / `max_depth` ceilings.\n- Plan the population the work needs and let the host queue and clamp it.\n These ceilings are enforcement, not a reason to pre-shrink a valid plan.\n\nSee the Workflow JS sandbox tests for the fail-closed host surface inventory.\n\n## Language Choice\n\n| Surface | Strength | Tradeoff | Stance |\n|---|---|---|---|\n| YAML / JSON IR | Simple, reviewable, no runtime | Verbose for generated workflows | Keep as interchange/debug format |\n| JavaScript | Familiar object syntax and easy agent generation | Unsafe if executed as a general runtime | First-class authoring through declarative compile-only subset |\n| TypeScript | Best editor/types story for workflow SDK | Needs stripping/typechecking if full TS is supported | Same compile-only subset for now; richer SDK later |\n\nThe default high-capability path is TypeScript/JavaScript authoring, but only as\na compile step. The compiler accepts a JSON-compatible object inside\n`workflow({...})` from `.workflow.js` or `.workflow.ts`, lowers it to\n`WorkflowSpec`, and runs the Rust validation gate. (Starlark authoring was a\nbootstrap reference and has been removed; Workflow authoring is JS-only.)\n\n## Contract\n\nAccepted source shape:\n\n```js\nexport default workflow({\n \"id\": \"issue-audit-js\",\n \"goal\": \"Audit an issue fix with parallel agents\",\n \"nodes\": [\n {\n \"branch\": {\n \"id\": \"parallel-audit\",\n \"children\": [\n { \"agent\": { \"id\": \"code-audit\", \"prompt\": \"Review code\", \"agent_type\": \"review\" } },\n { \"agent\": { \"id\": \"test-audit\", \"prompt\": \"Review tests\", \"agent_type\": \"verifier\" } }\n ]\n }\n },\n { \"reduce\": { \"id\": \"summary\", \"inputs\": [\"code-audit\", \"test-audit\"], \"prompt\": \"Summarize\" } }\n ]\n});\n```\n\nSupported node wrappers: `agent`, `branch`, `sequence`, `reduce`,\n`teacher_review`, `loop_until`, Line truncated
}
]
},
{
"id": "sandbox",
"slug": "sandbox",
"sources": [
{
"path": "docs/SANDBOX.md",
"sha256": "b26ef5b6de58dcd372a6e7a6c53b2a9e5a17f88151618cd45d14b237c37b7616",
"content": "# Sandbox threat model\n\n> 阅读简体中文版:[zh_hans/SANDBOX.md](zh_hans/SANDBOX.md)。\n\nCodewhale can launch shell commands proposed by a model. Approval policy,\nworkspace-aware tools, and an operating-system command wrapper are separate\ncontrols: an approval is not a sandbox, and selecting `workspace-write` does\nnot prove that the current platform has an OS wrapper available.\n\nThis document describes only behavior wired into the command execution path.\nSee [Authorization order](AUTHORIZATION_ORDER.md) for the policy layers that\nrun before execution reaches this boundary.\n\n## Platform overview\n\n| Mechanism | Platform | Selection | What Codewhale reports |\n|---|---|---|---|\n| Seatbelt (`sandbox-exec`) | macOS | Automatic when the runtime probe succeeds | `macos-seatbelt` |\n| Bubblewrap (`/usr/bin/bwrap`) | Linux | Default when installed and a wrapped probe run succeeds; `prefer_bwrap = false` opts out | `linux-bwrap` |\n| No OS wrapper | Linux without usable bwrap, or opted out | `prefer_bwrap = false`, or bwrap absent/unusable | `none` |\n| No OS wrapper | Windows | Current implementation | `none` |\n| OpenSandbox-compatible service | Any supported host | `sandbox_backend = \"opensandbox\"` | External execution path |\n\nThe repository contains a seccomp implementation module plus a future Windows\nhelper contract. They are not wired into child-command launch, so Codewhale\ndoes not advertise them as active sandboxes. Source-only sandbox code is not\nevidence that a command was restricted.\n\n## macOS: Seatbelt\n\nCodewhale probes `/usr/bin/sandbox-exec` by running a minimal profile. When the\nprobe succeeds and the selected `SandboxPolicy` requests a sandbox, the child\ncommand is wrapped with a generated Seatbelt profile.\n\nThe profile can provide:\n\n- broad filesystem reads;\n- writes limited by the selected policy, including the workspace and specific\n runtime/cache paths needed by supported tools;\n- network access only when the policy enables it.\n\nIf the probe fails or `sandbox-exec` is unavailable, Codewhale reports no OS\nsandbox and launches the command without a Seatbelt wrapper. It does not set a\nSeatbelt marker on that fallback.\n\n## Linux: default bubblewrap\n\nLinux command sandboxing is on by default whenever bubblewrap works. Set the\ntop-level configuration key to opt out:\n\n```toml\nprefer_bwrap = false\n```\n\nCodewhale selects bubblewrap only when `/usr/bin/bwrap` is a regular\nexecutable file AND a wrapped probe run proves it can create its namespaces\non this host — the exec bit alone lies where user namespaces are restricted\n(e.g. Ubuntu 24.04 with `kernel.apparmor_restrict_unprivileged_userns`),\nwhere every wrapped command would fail rather than run unsandboxed. The\nwrapper derives its mounts and network namespace from the resolved\n`SandboxPolicy`:\n\n```text\n/usr/bin/bwrap \\\n --unshare-all \\\n [--share-net] \\\n --ro-bind / / \\\n --dev /dev \\\n --proc /proc \\\n --tmpfs /tmp \\\n [--dev-bind <device-root> <device-root> ...] \\\n --bind <writable-root> <writable-root> ... \\\n --ro-bind <protected-descendant> <protected-descendant> ... \\\n [--ro-bind <extra-ro-root> <extra-ro-root> ...] \\\n --chdir <cwd> \\\n -- <program> <args>\n```\n\nThe sandbox always gets a private `/dev` (fresh device nodes, so `>/dev/null`\nworks), a private `/proc`, and a tmpfs `/tmp` (#5410). Two optional top-level\nconfig keys extend the mounts: `bwrap_ro_roots` (extra host paths bind-mounted\nread-only, applied last so they can narrow a policy-writable path) and\n`bwrap_dev_roots` (host character/block device nodes bind-mounted read-write;\ndirectories are never honored). Missing paths are skipped silently.\n\nThat gives the child a read-only root view. For `workspace-write`, every safe,\nexisting policy root is mounted read-write: the working directory, configured\nadditional roots, `/tmp` and `TMPDIR` unless excluded, and verified Git\nworktree metadata roots. Existing `.codewhale` and `.deepseek` descendants are\nremounted read-only after their writable parent. Missing paths, non-directory\npaths, and `/` are not promoted to writable mounts.\n\nFor `read-only`, there are no writable binds, so the working directory remains\ninside the read-only root view. `--unshare-all` isolates the network namespace\nby default. Codewhale adds `--share-net` only when the policy's\n`network_access` is true. `danger-full-access` and `external-sandbox` bypass the\nlocal wrapper entirely.\n\nIf the user opts out, or `/usr/bin/bwrap` is missing, non-executable, or\ncannot actually confine a child, Codewhale reports `none` and launches the\ncommand without a Linux OS wrapper. There is no marker-only fallback to a\ndifferent Linux sandbox.\n\nInstall bubblewrap separately to get enforcement on Linux:\n\n- Ubuntu/Debian: `apt install bubblewrap`\n- Fedora: `dnf install bubblewrap`\n- Arch: `pacman -S bubblewrap`\n\nCodewhale does not vendor bubbleLine truncated
},
{
"path": "docs/AUTHORIZATION_ORDER.md",
"sha256": "ae8199a642c58c9c8640405ad6d59ba55f9b18ef976d231767972bca1f52e830",
"content": "# Authorization order\n\n> 阅读简体中文版:[zh_hans/AUTHORIZATION_ORDER.md](zh_hans/AUTHORIZATION_ORDER.md)。\n\nCodewhale combines tool availability, hooks, typed permission rules, approval\nposture, repository policy, and sandboxing. An approval from one layer is not a\nuniversal bypass: a later safety layer can still require review or block the\ncall, and an approval is not an operating-system sandbox grant.\n\nThis page records the order implemented by the interactive engine's\nmodel-requested tool path. Entrypoints that use only part of that path, such as\nthe core runtime's direct tool API, keep the relative order of the layers they\ndo use.\n\n## Model tool-call pipeline\n\nThe interactive engine evaluates a model-requested tool call in this order:\n\n| Order | Layer | Result |\n|---:|---|---|\n| 1 | Effective configuration and posture | User settings, command/runtime overrides, and the project overlay resolve before the turn. A project overlay may tighten `approval_policy`, `sandbox_mode`, or shell availability, but may not loosen them. |\n| 2 | Mode and tool admission | Plan-mode restrictions, input parse errors, per-command tool deny/allow lists, caller restrictions, and missing execution registrations fail before policy rules are considered. A tool present in both command lists is denied. |\n| 3 | Preparation, then `tool_call_before` hooks | Registry preparation is side-effect free. Foreground hooks then fold as `deny > ask > allow`, and a strict matching hook that produces no verdict fails closed. The last `updatedInput` wins; the engine prepares the rewritten input again before later gates inspect it. |\n| 4 | Registered-tool baseline | The prepared tool's `ApprovalRequirement` establishes its ordinary approval need. A hook `ask` is applied after that assignment so the baseline cannot erase it. Non-bypassable registered holds remain forced in postures that can prompt; Full Access auto-approves them instead of opening a contradictory modal. Plan mode also blocks write-capable tools here. |\n| 5 | Typed `permissions.toml` rule | A matching `deny` blocks. A matching `allow` may clear only ordinary registry approval; it cannot clear a hook `ask` or a non-bypassable registered hold. A matching `ask` forces review only in a posture that can prompt. Full Access/auto-approval is not downgraded into a prompt, while an explicit typed `deny` still blocks. |\n| 6 | Auto-review policy and built-in safety floor | Configured block rules run before the built-in floor, then configured allow rules and the deterministic fallback. This layer runs after typed permissions and can add a prompt or block, but cannot remove an earlier hold. Full Access deliberately skips the interactive publish hold; catastrophic destructive background/headless actions remain protected. |\n| 7 | Repository law | Protected path invariants can only add a prompt or block. A repo-law prompt becomes a hard block in Full Access, which has no contradictory approval modal. |\n| 8 | Human approval | A remaining prompt is sent to the approval channel. Denial stops the call. Approval authorizes this planned call; session and persistent choices affect later matching calls but do not erase a later gate from this call. |\n| 9 | Tool authority and execution sandbox | Worker authority envelopes, native tool path checks, and the selected OS or external sandbox still apply during execution. A sandbox denial remains a denial unless the user separately authorizes a supported elevation path. |\n\nThe ordering is intentionally monotonic after the typed permission layer:\nauto-review and repository law can tighten a result, not turn a previous block\nor prompt into an unreviewed execution. There are explicit posture choices\ninside those layers—for example, Full Access does not create an interactive\npublish prompt—but those choices do not let an earlier remembered grant erase\na hold that the layer actually produced.\n\n## Typed permission-rule selection\n\n`permissions.toml` is currently a sibling of the active user `config.toml`.\nThere is no project-local permission-rule source today. An optional `workspace`\nfield scopes one user rule to a repository; it does not create a project\noverlay. `/permissions` reports that source, matcher, scope, and whether the\nscope applies to the current workspace.\n\nThe execution-policy engine evaluates matching rules as follows:\n\n1. Normalize the tool, command, workspace, and any workspace-relative path.\n Unsafe or external paths do not become matchable file rules.\n2. Check denied command prefixes against the whole command and every chained\n segment. These hard prefix denies are merged across rulesets and always win.\n3. Compute a trusted-prefix candidate for an unchained shell command. This is a\n candidate for the approval-mode fallback, not an immediate decision.\n4. Select one matching typed rule by this lexicographic precedence:\n 1. higher source layer: `User > Agent Line truncated
}
]
},
{
"id": "trust",
"slug": "trust",
"sources": [
{
"path": "docs/SANDBOX.md",
"sha256": "b26ef5b6de58dcd372a6e7a6c53b2a9e5a17f88151618cd45d14b237c37b7616",
"content": "# Sandbox threat model\n\n> 阅读简体中文版:[zh_hans/SANDBOX.md](zh_hans/SANDBOX.md)。\n\nCodewhale can launch shell commands proposed by a model. Approval policy,\nworkspace-aware tools, and an operating-system command wrapper are separate\ncontrols: an approval is not a sandbox, and selecting `workspace-write` does\nnot prove that the current platform has an OS wrapper available.\n\nThis document describes only behavior wired into the command execution path.\nSee [Authorization order](AUTHORIZATION_ORDER.md) for the policy layers that\nrun before execution reaches this boundary.\n\n## Platform overview\n\n| Mechanism | Platform | Selection | What Codewhale reports |\n|---|---|---|---|\n| Seatbelt (`sandbox-exec`) | macOS | Automatic when the runtime probe succeeds | `macos-seatbelt` |\n| Bubblewrap (`/usr/bin/bwrap`) | Linux | Default when installed and a wrapped probe run succeeds; `prefer_bwrap = false` opts out | `linux-bwrap` |\n| No OS wrapper | Linux without usable bwrap, or opted out | `prefer_bwrap = false`, or bwrap absent/unusable | `none` |\n| No OS wrapper | Windows | Current implementation | `none` |\n| OpenSandbox-compatible service | Any supported host | `sandbox_backend = \"opensandbox\"` | External execution path |\n\nThe repository contains a seccomp implementation module plus a future Windows\nhelper contract. They are not wired into child-command launch, so Codewhale\ndoes not advertise them as active sandboxes. Source-only sandbox code is not\nevidence that a command was restricted.\n\n## macOS: Seatbelt\n\nCodewhale probes `/usr/bin/sandbox-exec` by running a minimal profile. When the\nprobe succeeds and the selected `SandboxPolicy` requests a sandbox, the child\ncommand is wrapped with a generated Seatbelt profile.\n\nThe profile can provide:\n\n- broad filesystem reads;\n- writes limited by the selected policy, including the workspace and specific\n runtime/cache paths needed by supported tools;\n- network access only when the policy enables it.\n\nIf the probe fails or `sandbox-exec` is unavailable, Codewhale reports no OS\nsandbox and launches the command without a Seatbelt wrapper. It does not set a\nSeatbelt marker on that fallback.\n\n## Linux: default bubblewrap\n\nLinux command sandboxing is on by default whenever bubblewrap works. Set the\ntop-level configuration key to opt out:\n\n```toml\nprefer_bwrap = false\n```\n\nCodewhale selects bubblewrap only when `/usr/bin/bwrap` is a regular\nexecutable file AND a wrapped probe run proves it can create its namespaces\non this host — the exec bit alone lies where user namespaces are restricted\n(e.g. Ubuntu 24.04 with `kernel.apparmor_restrict_unprivileged_userns`),\nwhere every wrapped command would fail rather than run unsandboxed. The\nwrapper derives its mounts and network namespace from the resolved\n`SandboxPolicy`:\n\n```text\n/usr/bin/bwrap \\\n --unshare-all \\\n [--share-net] \\\n --ro-bind / / \\\n --dev /dev \\\n --proc /proc \\\n --tmpfs /tmp \\\n [--dev-bind <device-root> <device-root> ...] \\\n --bind <writable-root> <writable-root> ... \\\n --ro-bind <protected-descendant> <protected-descendant> ... \\\n [--ro-bind <extra-ro-root> <extra-ro-root> ...] \\\n --chdir <cwd> \\\n -- <program> <args>\n```\n\nThe sandbox always gets a private `/dev` (fresh device nodes, so `>/dev/null`\nworks), a private `/proc`, and a tmpfs `/tmp` (#5410). Two optional top-level\nconfig keys extend the mounts: `bwrap_ro_roots` (extra host paths bind-mounted\nread-only, applied last so they can narrow a policy-writable path) and\n`bwrap_dev_roots` (host character/block device nodes bind-mounted read-write;\ndirectories are never honored). Missing paths are skipped silently.\n\nThat gives the child a read-only root view. For `workspace-write`, every safe,\nexisting policy root is mounted read-write: the working directory, configured\nadditional roots, `/tmp` and `TMPDIR` unless excluded, and verified Git\nworktree metadata roots. Existing `.codewhale` and `.deepseek` descendants are\nremounted read-only after their writable parent. Missing paths, non-directory\npaths, and `/` are not promoted to writable mounts.\n\nFor `read-only`, there are no writable binds, so the working directory remains\ninside the read-only root view. `--unshare-all` isolates the network namespace\nby default. Codewhale adds `--share-net` only when the policy's\n`network_access` is true. `danger-full-access` and `external-sandbox` bypass the\nlocal wrapper entirely.\n\nIf the user opts out, or `/usr/bin/bwrap` is missing, non-executable, or\ncannot actually confine a child, Codewhale reports `none` and launches the\ncommand without a Linux OS wrapper. There is no marker-only fallback to a\ndifferent Linux sandbox.\n\nInstall bubblewrap separately to get enforcement on Linux:\n\n- Ubuntu/Debian: `apt install bubblewrap`\n- Fedora: `dnf install bubblewrap`\n- Arch: `pacman -S bubblewrap`\n\nCodewhale does not vendor bubbleLine truncated
},
{
"path": "docs/AUTHORIZATION_ORDER.md",
"sha256": "ae8199a642c58c9c8640405ad6d59ba55f9b18ef976d231767972bca1f52e830",
"content": "# Authorization order\n\n> 阅读简体中文版:[zh_hans/AUTHORIZATION_ORDER.md](zh_hans/AUTHORIZATION_ORDER.md)。\n\nCodewhale combines tool availability, hooks, typed permission rules, approval\nposture, repository policy, and sandboxing. An approval from one layer is not a\nuniversal bypass: a later safety layer can still require review or block the\ncall, and an approval is not an operating-system sandbox grant.\n\nThis page records the order implemented by the interactive engine's\nmodel-requested tool path. Entrypoints that use only part of that path, such as\nthe core runtime's direct tool API, keep the relative order of the layers they\ndo use.\n\n## Model tool-call pipeline\n\nThe interactive engine evaluates a model-requested tool call in this order:\n\n| Order | Layer | Result |\n|---:|---|---|\n| 1 | Effective configuration and posture | User settings, command/runtime overrides, and the project overlay resolve before the turn. A project overlay may tighten `approval_policy`, `sandbox_mode`, or shell availability, but may not loosen them. |\n| 2 | Mode and tool admission | Plan-mode restrictions, input parse errors, per-command tool deny/allow lists, caller restrictions, and missing execution registrations fail before policy rules are considered. A tool present in both command lists is denied. |\n| 3 | Preparation, then `tool_call_before` hooks | Registry preparation is side-effect free. Foreground hooks then fold as `deny > ask > allow`, and a strict matching hook that produces no verdict fails closed. The last `updatedInput` wins; the engine prepares the rewritten input again before later gates inspect it. |\n| 4 | Registered-tool baseline | The prepared tool's `ApprovalRequirement` establishes its ordinary approval need. A hook `ask` is applied after that assignment so the baseline cannot erase it. Non-bypassable registered holds remain forced in postures that can prompt; Full Access auto-approves them instead of opening a contradictory modal. Plan mode also blocks write-capable tools here. |\n| 5 | Typed `permissions.toml` rule | A matching `deny` blocks. A matching `allow` may clear only ordinary registry approval; it cannot clear a hook `ask` or a non-bypassable registered hold. A matching `ask` forces review only in a posture that can prompt. Full Access/auto-approval is not downgraded into a prompt, while an explicit typed `deny` still blocks. |\n| 6 | Auto-review policy and built-in safety floor | Configured block rules run before the built-in floor, then configured allow rules and the deterministic fallback. This layer runs after typed permissions and can add a prompt or block, but cannot remove an earlier hold. Full Access deliberately skips the interactive publish hold; catastrophic destructive background/headless actions remain protected. |\n| 7 | Repository law | Protected path invariants can only add a prompt or block. A repo-law prompt becomes a hard block in Full Access, which has no contradictory approval modal. |\n| 8 | Human approval | A remaining prompt is sent to the approval channel. Denial stops the call. Approval authorizes this planned call; session and persistent choices affect later matching calls but do not erase a later gate from this call. |\n| 9 | Tool authority and execution sandbox | Worker authority envelopes, native tool path checks, and the selected OS or external sandbox still apply during execution. A sandbox denial remains a denial unless the user separately authorizes a supported elevation path. |\n\nThe ordering is intentionally monotonic after the typed permission layer:\nauto-review and repository law can tighten a result, not turn a previous block\nor prompt into an unreviewed execution. There are explicit posture choices\ninside those layers—for example, Full Access does not create an interactive\npublish prompt—but those choices do not let an earlier remembered grant erase\na hold that the layer actually produced.\n\n## Typed permission-rule selection\n\n`permissions.toml` is currently a sibling of the active user `config.toml`.\nThere is no project-local permission-rule source today. An optional `workspace`\nfield scopes one user rule to a repository; it does not create a project\noverlay. `/permissions` reports that source, matcher, scope, and whether the\nscope applies to the current workspace.\n\nThe execution-policy engine evaluates matching rules as follows:\n\n1. Normalize the tool, command, workspace, and any workspace-relative path.\n Unsafe or external paths do not become matchable file rules.\n2. Check denied command prefixes against the whole command and every chained\n segment. These hard prefix denies are merged across rulesets and always win.\n3. Compute a trusted-prefix candidate for an unchained shell command. This is a\n candidate for the approval-mode fallback, not an immediate decision.\n4. Select one matching typed rule by this lexicographic precedence:\n 1. higher source layer: `User > Agent Line truncated
},
{
"path": "docs/TELEMETRY.md",
"sha256": "6e69aec8fe595b6d40bd63c71cfaea6cc980ca7b1adaa09b9e4920c50bfe3d53",
"content": "# Codewhale product telemetry\n\n> 阅读简体中文版:[zh_hans/TELEMETRY.md](zh_hans/TELEMETRY.md)\n\n**Usage analytics are on by default in the current source.** The first\ninteractive launch gives a localized, nonblocking disclosure naming **Codewhale\nand PostHog**, with a direct route to turn counting off. Notice version `5`\ndescribes this policy; displaying it is not recorded as human acceptance.\nMissing an older acceptance record does not turn a fresh installation off.\nExisting explicit opt-outs remain off across upgrades, and unreadable privacy\nstate fails closed. Environment and CLI kill switches still take precedence.\n\nRead the disclosure with `codewhale config telemetry`. Turn usage off in\n`/settings` or run `codewhale config set telemetry false`. Turning it back on\nin Settings or with `codewhale config set telemetry true` updates the existing\ndurable preference and privacy records for new sessions. The compatibility\ncommand `codewhale config telemetry --accept-notice 5` remains available, but\nis not required for a fresh installation. Collection never includes work content or credentials.\n\nThe PostHog sink is optional and inert until the ingest operator explicitly\nconfigures a project token and approved regional host, and records staging\nproof that the actual egress path does not forward the original client IP.\nSource readiness does not establish a deployment, an activated processor,\nan egress receipt, or a retention setting.\n\nCodewhale does not collect conversations, code, prompts, files, file/repo/branch\nnames, model content, or credentials. It sends no per-turn or per-tool timeline.\nIt does send the closed, aggregate schema below: version and platform classes,\nsession duration/outcome, feature/error counters, and a random install id that\nrotates every 90 days.\n\n**There is now a real endpoint.** An enabled session sends its batches to the\nfirst-party ingest service at `https://telemetry.codewhale.net/v1/telemetry`,\nwhich is the shipped default for `telemetry_endpoint`. What that service is,\nwhat it stores, and what it structurally cannot store is spelled out in \"What\nthe endpoint does\" below.\n\n**To send nothing anywhere, turn telemetry off** (see \"Turning it off\"). To stay\nenabled but contact nobody, set `telemetry_endpoint = \"\"`: batches are then\nappended to `$CODEWHALE_HOME/telemetry/dryrun.jsonl` on your own machine, byte\nfor byte what the server would have received, and no HTTP client is ever\nconstructed. That file is how you audit this document against reality.\n\nThis document is the schema. It is not a summary of the schema: a test in\n`crates/telemetry` parses the field names out of this file and asserts set\nequality against the structs the serializer actually uses, so a field that is\nhere and not in the code — or in the code and not here — fails the build.\n\nLocal saved sessions and `codewhale metrics` remain available with telemetry\ndisabled and require no account or hosted reporting service. Disabling telemetry\ndoes not disable local usage receipts.\n\n## Turning it off\n\nThere are two off switches and they do different things. Both stop collection\ncompletely; only one of them erases anything.\n\n```sh\ncodewhale config set telemetry false # opt out: stops collection and erases state\nCODEWHALE_TELEMETRY=0 codewhale # kill switch: stops collection, erases nothing\ncodewhale --telemetry false # the same kill switch, for one command\n```\n\n**`telemetry = false` in the config file is the opt-out.** It is a floor:\n`--telemetry true` and `CODEWHALE_TELEMETRY=1` both lose to it, because a\nsetting you can undo by accident from a wrapper script is not a setting. It\ndeletes the random install id, truncates every buffered event and every dry-run\nrecord, and writes a tombstone. Appends, identity/state writes, and delivery all\nshare the wipe's ordering lock, so once opt-out returns no pre-opt-out write or\nPOST remains in flight. If any part of that wipe fails, the tombstone is still\nthere and the buffer is undrainable — a failed wipe fails closed. Every later\nrun re-asserts the same tombstone for as long as the setting stands, so it\nsurvives. Turning telemetry back on in `/settings` records that explicit preference\nin both existing privacy registers; a fresh launch can then clear the tombstone. Nothing buffered before that point is\never sent.\n\n**The environment variable and the flag are kill switches, not opt-outs.**\nTelemetry is off for the run, nothing is written, nothing is sent — and\nnothing on disk is touched or deleted. That is deliberate: a harness or agent\nthat sets `CODEWHALE_TELEMETRY=0` for one command must not silently discard the\ninstall id and the dry-run records of the person who owns the machine. If you\nwant the erasing kind, use the config file.\n\n`CODEWHALE_TELEMETRY` (and its `DEEPSEEK_TELEMETRY` alias) accepts\n`0`, `1`, `true`, `false`, `yes`, `no`, Line truncated
},
{
"path": "docs/public-surface-facts.json",
"sha256": "1d688a9b6a08de2bbf5e1122594aa1e0b47cb30cc7d94e27b8d4df7a7ba86a26",
"content": "{\n \"schemaVersion\": 2,\n \"product\": {\n \"name\": \"Codewhale\",\n \"description\": \"Terminal coding agent for supported hosted and local models. One runtime on your machine. Rust, MIT.\",\n \"positioning\": \"Terminal-native, model/provider-neutral, local-first coding agent\",\n \"license\": \"MIT\",\n \"terminology\": {\n \"Fleet\": \"the user's model inventory: who is in the roster and which member is selected\",\n \"Workflow\": \"what order the work follows\",\n \"Lane\": \"one running Workflow instance\",\n \"Runtime\": \"where, how, and with what authority selected work executes\"\n },\n \"sources\": [\n \"Cargo.toml\",\n \"LICENSE\",\n \"README.md\",\n \"npm/codewhale/package.json\",\n \"docs/FLEET.md\"\n ]\n },\n \"sourceCandidate\": {\n \"version\": \"0.10.2\",\n \"providerCount\": 50,\n \"toolCount\": 79,\n \"sandboxBackends\": [\n \"seatbelt (macOS, when available)\",\n \"bubblewrap (Linux, default when installed and working)\"\n ],\n \"sources\": [\n \"Cargo.toml\",\n \"crates/tui/src/config.rs\",\n \"crates/tui/src/sandbox/mod.rs\",\n \"web/scripts/derive-facts.mjs\"\n ],\n \"providerCountDefinition\": \"Website descriptor identities in this source snapshot, excluding Custom and retired identities; includes protocol/plan variants. Not a count of distinct vendors, ProviderKind identities, live catalogs, or providers in any published release.\"\n },\n \"latestPublishedRelease\": {\n \"tag\": \"v0.10.1\",\n \"version\": \"0.10.1\",\n \"publishedAt\": \"2026-10-08T01:47:44Z\",\n \"url\": \"https://github.com/codewhale-hq/CodeWhale/releases/tag/v0.10.1\",\n \"sources\": [\n \"web/data/latest-published-release.json\"\n ]\n },\n \"install\": {\n \"recommended\": \"curl -fsSL https://codewhale.net/install.sh | sh\",\n \"binaries\": [\n \"codewhale\",\n \"codew\"\n ],\n \"channels\": {\n \"npm\": \"published releases only\",\n \"cargo\": \"published crates only\",\n \"prebuiltArchives\": \"published GitHub Releases only\",\n \"cnbMirror\": \"documented targets only\"\n },\n \"androidTermux\": {\n \"status\": \"preview\",\n \"npm\": \"preview\",\n \"requiresMatchingPublishedAssets\": true,\n \"sourceBuild\": true\n },\n \"sources\": [\n \"README.md\",\n \"npm/codewhale/package.json\",\n \"npm/codewhale/README.md\",\n \"npm/codewhale/scripts/artifacts.js\",\n \"docs/INSTALL.md\",\n \"docs/CNB_MIRROR.md\"\n ]\n },\n \"control\": {\n \"modes\": [\n \"Plan\",\n \"Work\",\n \"Operate\"\n ],\n \"permissionPostures\": [\n \"Ask\",\n \"Auto-Review\",\n \"Full Access\"\n ],\n \"shortcuts\": {\n \"mode\": {\n \"chord\": \"Tab\",\n \"when\": \"composer empty\"\n },\n \"permissionPosture\": {\n \"chord\": \"Shift+Tab\",\n \"when\": \"always (suppressed only under a non-Config modal)\"\n }\n },\n \"sources\": [\n \"docs/MODES.md\",\n \"docs/KEYBINDINGS.md\",\n \"crates/tui/src/settings.rs\"\n ]\n },\n \"toolSurface\": {\n \"defaultActive\": [\n \"read\",\n \"write\",\n \"edit\",\n \"file_search\",\n \"bash\",\n \"agent\",\n \"workflow\",\n \"todo_write\",\n \"create_goal\",\n \"get_goal\",\n \"update_goal\",\n \"load_skill\"\n ],\n \"schemas\": {\n \"read\": [\n \"path\",\n \"offset?\",\n \"limit?\"\n ],\n \"write\": [\n \"path\",\n \"content\"\n ],\n \"edit\": [\n \"path\",\n \"edits\"\n ],\n \"bash\": [\n \"command\",\n \"timeout?\"\n ]\n },\n \"deferred\": {\n \"Web\": [\n \"search\",\n \"fetch\",\n \"wait\"\n ]\n },\n \"compatibility\": {\n \"legacyAliases\": \"hidden-exact\",\n \"modelVisible\": false,\n \"toolSearchDiscoverable\": false\n },\n \"activationCache\": {\n \"maximumNames\": 8,\n \"maximumSchemaBytes\": 16384,\n \"scope\": \"per conversation; each subagent owns an independent policy-filtered cache\"\n },\n \"agentConcurrency\": {\n \"defaultConfigured\": 64,\n \"maximumConfigured\": 128,\n \"maximumAdmitted\": 1024\n },\n \"sources\": [\n \"docs/TOOL_SURFACE.md\",\n \"docs/RUNTIME_SIMPLIFICATION_DESIGN.md\",\n \"crates/tui/src/core/engine/tool_catalog.rs\",\n \"crates/tui/src/tools/registry.rs\",\n \"crates/tui/src/config/subagent_limits.rs\"\n ]\n },\n \"surfaces\": {\n \"availableInSourceCandidate\": [\n \"TUI\",\n \"codewhale exec\",\n \"Web client\",\n \"Runtime API\",\n \"MCP\",\n \"Fleet\"\n ],\n \"sources\": [\n \"docs/GUIDE.md\",\n \"docs/WELine truncated
},
{
"path": "docs/PREVIEW_REQUEST.md",
"sha256": "3723e8f84ccf3199c4c0b7408f2b2e905a7efe29253fb7928e6acb0ebe9581e0",
"content": "# `/preview-request` — see the outbound request without sending it\n\n`/preview-request` renders a **request manifest**: a typed, redacted\ndescription of the request the next **primary agent turn** would send. It never\nsends that request, never appends to the conversation, and never writes engine,\nsession, or Work state. `/dryrun` and `/preview_request` are compatibility\naliases.\n\nIt is a human command. There is deliberately no model-visible tool for it.\n\n```\n/preview-request # session facts; route/body reported unavailable\n/preview-request json # same manifest as JSON\n/preview-request --prompt <text> # the next turn for that prompt\n/preview-request json --prompt <text> # both\n/preview-request base-prompt # exact base layer only; no runtime additions\n```\n\n### Argument grammar\n\n```\nargs := flag* [ \"--prompt\" <whitespace> prompt ]\nflag := json | --json | manifest | --manifest | prompt | base-prompt | --base-prompt\nprompt := every remaining byte, verbatim\n```\n\n**Flags come before `--prompt`, which is terminal.** Everything after it is\nprompt text — including a trailing `json`. `/preview-request --prompt fix it\njson` previews the prompt *\"fix it json\"* as a human table; the JSON spelling\nis `/preview-request json --prompt fix it`. There is exactly one reading of any\ninput, and an unknown argument before `--prompt` is rejected rather than\nguessed at.\n\n**The prompt keeps your bytes.** Repeated whitespace and newlines inside it\nsurvive; exactly one whitespace codepoint separates `--prompt` from its text\nand is consumed as syntax. Any additional leading whitespace, plus all\ntrailing whitespace and newlines, remains prompt data. The prompt is hashed\ninto the previewed body, so normalizing it would describe a request that\ndiffers from the real one in the one field you typed.\n\n`prompt` remains a compatibility alias for the ordinary protected manifest.\n`base-prompt` / `--base-prompt` are an explicit, human-only disclosure mode:\nthey print exactly the effective base-prompt bytes and nothing else. They\ncannot be combined with JSON or `--prompt`. Effective system text is never\nprinted because it can contain project instructions, skills, and memory.\n\n## `--prompt` is necessary for an exact manifest, and not always sufficient\n\nThe next user message is **part of the request**. Without it there is no\nnext-turn body to describe, and under auto model routing there is not even a\nroute: the route is decided by the text you have not typed yet.\n\nSo the manifest is sectioned, and each section is either exact or typed-absent:\n\n| Section | Exact when |\n| --- | --- |\n| `session` | always — posture, gates, base-prompt provenance, requested model/reasoning |\n| `route` | `--prompt` was supplied, an active goal has not exhausted its token budget, a fixed route is selected, no `message_submit` hooks are configured, and the shared planner resolved that route |\n| `tools` | the route is exact **and** the MCP tool state can be snapshotted without connecting |\n| `body` | the tool surface and authoritative Work snapshot are exact **and** no runtime transform would rewrite the request first |\n\n### Why a section stops being exact\n\n| Typed reason | What a real turn would do that an inspection may not |\n| --- | --- |\n| `auto-route-unresolved-until-next-prompt` | decide the route from text you have not typed |\n| `auto-route-classification-not-executed` | call the provider-backed Auto classifier; preview is strictly offline, so production must resolve it |\n| `no-hypothetical-prompt-supplied` | send a message the manifest does not have |\n| `message-submit-hooks-not-executed` | run mutable hooks that can rewrite or block the text — and therefore the route, tool policy, and body derived from it |\n| `prompt-resolution-failed` | fail the same way on skill authority or file mentions |\n| `route-plan-failed` | fail route resolution or preflight |\n| `mcp-state-not-snapshottable` | connect MCP servers and discover tools this catalog does not contain |\n| `runtime-transforms-before-send` | auto-compact, run context-overflow recovery, inject a background-shell completion, allow a running or terminal-undelivered child to complete, or flush pending LSP diagnostics before the first request |\n| `work-state-not-snapshottable` | read the current graph-backed Work projection; preview never substitutes an asynchronously published, potentially stale To-do view |\n| `goal-token-budget-exhausted` | stop the active goal before dispatch because durable token usage has reached the configured budget |\n| `goal-state-not-snapshottable` | decide whether the active goal's terminal budget gate permits another request |\n| `request-preparation-failed` | build no body at all |\n\n**`mcp-state-not-snapshottable` takes the body with it.** A catalog missing its\nMCP contribution is not \"the same request with no MCP tools\" — a reLine truncated
}
]
},
{
"id": "mcp",
"slug": "mcp",
"sources": [
{
"path": "docs/MCP.md",
"sha256": "42484aab539d347e3890d5f164135e00a75bdf51a12af500c9343d02cd93dc37",
"content": "# MCP (External Tool Servers)\n\nIn the terminal, `/mcp` (also `/mcps`) opens **Extensions → MCP**. Enter opens the selected server’s recovery action or read-only details. An empty inventory offers server suggestions; browsing them installs nothing. Explicit subcommands such as `/mcp status`, `/mcp doctor`, `/mcp login`, and `/mcp add` retain their existing behavior.\n\n\n> 阅读简体中文版:[zh_hans/MCP.md](zh_hans/MCP.md)\n\ncodewhale can load additional tools via MCP (Model Context Protocol). MCP servers can be local stdio processes that the TUI starts, or remote URL-based servers that speak Streamable HTTP with legacy SSE fallback.\n\nBrowsing note:\n- `Web` is the canonical, deferred built-in browsing tool; it provides\n `search`, `fetch`, and `wait` actions when network policy permits.\n- `web_search`, `fetch_url`, and `wait_for_dev_server` are hidden replay-only\n aliases. New prompts and integrations should use `Web`.\n\nServer mode note:\n- `codewhale serve --mcp` runs the MCP stdio server.\n- `codewhale serve --http` runs the runtime HTTP/SSE API (separate mode).\n- `codewhale mcp-server` is an equivalent stdio entrypoint on the same\n consolidated runtime.\n\nIn 0.10.1, the old child-server aggregation proxy is removed. `mcp-server`\nnow uses the same native tool server as `serve --mcp`; it does not launch the\nlegacy `mcp.server_definitions` list. Saved definitions are left intact. Configure\nexternal servers in `mcp.json` for the existing MCP client, or connect to those\nservers directly from your external client. Native server write tools remain\nwithheld unless the operator explicitly permits them in its server configuration.\n\n## Setup wizard vs manual MCP setup (#3407)\n\nThe `/setup` hub includes an optional **Tools and MCP**\nstep. That step is discovery/readiness only:\n\n| Wizard can do | Still requires manual / explicit action |\n| --- | --- |\n| Show configured servers as `healthy` / `needs_config` / `off` | Start or connect MCP servers |\n| Report config path presence (global + project) | Write or edit `mcp.json` contents |\n| Safe static health probe (missing command/url, broken absolute path, missing bearer env) | `codewhale mcp validate`, live connect, OAuth login |\n| Point at safe on-ramps (`/mcp`, `codewhale mcp init`, `codewhale doctor`) | Install community skills, trust skills, enable plugins |\n| Share Hotbar source counts from the same skill/MCP adapters (#3399) | Bind Hotbar slots (Hotbar step / `H`) |\n| Record optional/`needs_action` setup_state without blocking first-run | Anything that spawns processes or installs packages |\n\nEmpty inventory is **not** an error: first-run users see “nothing configured\nyet, that’s fine.” Failing or incomplete configured servers surface as\n`needs_config` with an actionable hint and never block setup completion.\nEnumeration never executes MCP/plugin commands beyond the static probe.\nSummaries redact commands, args, env, headers, and tokens.\n\n`codewhale doctor` reports MCP/skills/tools/plugins health with the same\noptional-surface intent (paths, counts, static checks) so wizard and doctor\nstay consistent.\n\n## Plugin-contributed MCP\n\nA reviewed local plugin bundle may contribute MCP servers without creating a\nsecond transport or approval system. The servers use the same MCP manager,\ntool approval, resource, prompt, timeout, and network-policy paths documented\nhere, and appear under namespaced `<plugin>-<server>` identities.\n\nThe bundle boundary is intentionally stricter than user-authored `mcp.json`:\nunknown fields and ambiguous transports fail closed; stdio environment values\nmust be exact environment-source references; remote literal headers and\nsecret-bearing URLs are rejected; declared network hosts must exactly match\nthe normalized endpoint host set; and redirects remain on the reviewed origin.\nReviewed plugin remotes also bypass ambient HTTP proxy configuration entirely;\nproxy credentials and proxy-observed traffic are not part of the v1 review.\nThe plugin review discloses local host-user authority, structural argv,\nenvironment provenance, endpoint, auth source names, scopes, and tool filters\nwithout reading or printing secret values.\n\nTrust stages reviewed content but does not enable it. Enablement attaches that\nstaged snapshot to the current workspace's MCP pool. Disable, revoke, and other\ncross-process generation changes remove catalog entries, cancel in-flight\noperations, and terminate plugin stdio children. Source or staged-tree drift is\nfully revalidated before each dispatch/catalogue boundary and fails the next\nboundary closed; v0.9.1 does not continuously hash mutable trees during an\nalready-running call and therefore does not promise drift-triggered mid-call\ncancellation. MCP subscriptions are not exposed through plugin bundles. See\n[Plugin bundles](PLUGIN_BUNDLES.md) for the complete lifecycle contract.\n\n## Bootstrap MCP Config\n\nCreate a startLine truncated
}
]
},
{
"id": "hooks",
"slug": "hooks",
"sources": [
{
"path": "docs/rfcs/1364-hooks-lifecycle.md",
"sha256": "f57658326cdde29ee8c794ec4ca3eecd44a658b8c33116639a0ab481f8ae2be2",
"content": "# RFC: Hook Lifecycle Data Flow\n\n**Issue:** #1364\n**Status:** Implemented (all three PRs landed)\n**Date:** 2026-05-28\n**Reference:** the shipped contract lives in [docs/HOOKS.md](../HOOKS.md);\nthis RFC is kept as the design record. Where the two disagree, `docs/HOOKS.md`\nis correct and this document is history.\n\n**Scope:** everything below landed as a **TUI runtime** feature. No hook in\nthis RFC fires from `codewhale exec`, the CLI subcommands, the app-server /\nACP surfaces, or the `workflow` tool. The RFC's use of \"Codewhale\" as the\nactor should be read as \"the Codewhale TUI\" throughout.\n\n## 0. Implementation status\n\nVerified against `crates/tui/src/hooks/` and its call sites:\n\n| Item | Status | Where |\n| --- | --- | --- |\n| PR 1 — mutable `message_submit` | implemented | `HookExecutor::execute_message_submit_transform`, called from `dispatch_user_message_with_recovery` |\n| PR 2 — `turn_end` | implemented | `HookEvent::TurnEnd`, `turn_end_payload`, fired by `execute_turn_end_observer_hook` |\n| PR 3 — subagent observers | implemented | `HookEvent::SubagentSpawn` / `SubagentComplete`, fired by `execute_subagent_observer_hook` |\n\nTwo deliberate deltas from the text below, both shipped:\n\n- **`tool_call_before` also became mutable** (#3026), which this RFC listed as a\n non-goal for PR 1. It carries its own stdout JSON contract\n (`decision` / `reason` / `updatedInput` / `additionalContext`) plus the legacy\n exit-code-`2` hard deny. `message_submit` is therefore no longer the only\n event with a stdout contract; `shell_env`'s `KEY=VALUE` contract also predates\n both.\n- **`turn_end` observers are not gated by `continue_on_error`.** The structured\n observer path runs every matching hook regardless, because an observer that\n fails must not suppress the observers behind it.\n\nStill unimplemented from the text below: nothing in scope. `stop_hook_active` is\nemitted as `false` and the re-entry protection it reserves room for has not been\nbuilt.\n\nFour contract points hardened after this RFC, all documented in\n`docs/HOOKS.md`:\n\n- **One session identity.** The hook session id is minted once per TUI launch\n and survives a workspace switch or a trust decision that adds project hooks.\n `tool_call_before` reports that id rather than the engine's own session id,\n and `mode_change` carries it at all (it previously carried no session id).\n- **Timeouts bind background hooks too.** A background hook is supervised on\n its own thread; on expiry its process group is killed and reaped.\n- **`background` describes scheduling, not capability.** A background hook\n receives the same stdin payload and environment as the foreground form; it\n is simply never awaited, so its `HookResult` is flagged as a submission and\n carries no exit code.\n- **Conditions that can never match are rejected at load** rather than left\n silently inert — per entry, so a broken hook does not take a same-named or\n likewise-unnamed sibling with it — and a `tool_call_before` gate that returns\n no verdict does not read as permission when *that gate* declared\n `continue_on_error = false`. Strictness rides on the hook result, so it\n applies only to the hooks whose conditions matched the call in question.\n\n## 1. Problem\n\nCodewhale already has lifecycle hooks and MCP support, but the current hook\nsurface is mostly observer-only. This blocks portable extensions that need to\nparticipate in the agent data flow:\n\n- memory/context injection before a user message reaches the model\n- post-turn background analysis that prepares context for the next turn\n- sub-agent lifecycle visibility for orchestration and audit extensions\n\nThe current `message_submit` event fires before dispatch, but its output is\nignored. `TurnComplete`, `AgentSpawned`, and `AgentComplete` exist internally,\nbut they are not exposed as configurable hook events.\n\n## 2. PR split\n\nThis issue should be implemented as three PRs. Each PR should be independently\nreviewable and should leave the hook system in a useful state.\n\n### PR 1: Mutable `message_submit`\n\nAdd a structured hook execution path for `message_submit` that can transform or\nblock the user's submitted text before it is sent to the engine.\n\nScope:\n\n- keep the existing `[[hooks.hooks]]` config shape\n- pass a JSON payload to the hook on stdin\n- interpret stdout JSON containing `text` as the replacement user text\n- treat exit code `2` as an intentional block\n- run multiple submit hooks serially in config order\n- keep existing env vars for compatibility\n- keep `shell_env` stdout parsing unchanged\n\nNon-goals:\n\n- no tool argument mutation\n- no global stdout JSON semantics for all hook events\n- no transcript or model response mutation\n\n### PR 2: `turn_end`\n\nExpose the existing turn completion lifecycle as a hook event.\n\nScope:\n\n- add `HookEvent::TurnEnd` with event name `turn_end`\n- fire from the UI's `EngineLine truncated
},
{
"path": "docs/CONFIGURATION.md",
"sha256": "3dbae94838073e457a57abd5ec59d1b0ef5be5dc0ae358f515f6e5b6ffe3b23f",
"content": "# Configuration\n\ncodewhale reads configuration from a TOML file plus environment variables.\nAt process startup it may also load literal built-in-provider credentials from\na workspace-local `.env` file. Use the tracked `.env.example` as the template;\ncopy it to `.env`, then add only credential values.\n\nA workspace is not configuration authority. Codewhale therefore ignores\nconfig/profile/home paths, provider/model/base-URL routing, MCP/plugin state,\napproval/sandbox/shell posture, executable paths, runtime settings, and every\nother non-credential `.env` entry. Variable expansion is rejected so a\nrepository cannot substitute an ambient secret into a credential value. Use\n`config.toml`, CLI flags, or values exported by the launching shell for those\nexplicit control-plane settings. `.env` is read from a stable regular-file\nhandle, is capped at 1 MiB, and symbolic links, reparse points, and multiply\nlinked files are rejected.\n\n## Reading and checking configuration from the CLI\n\n`codewhale config get <key>` reads scalar keys, whole tables such as `tools`,\nand nested paths such as `tools.user_input_timeout_seconds`. Displayed tables\nand nested values apply the same recursive credential redaction as `config dump`.\n\n`config set` supports its named scalar keys and the provider, route, and\nnotification commands. It refuses a key that nothing reads and suggests the\nnearest real key (`config set calm_mod on` names `calm_mode`). A settings.toml\nkey such as `calm_mode` or `tool_collapse` is validated and written to the\nuser-global settings.toml, not config.toml; `config get` reads it back from\nthere even when an old config.toml copy (which nothing reads) is still present,\nand names that copy so you can `config unset` it. Settings keys have no project\nscope, so `--project` refuses them. A config.toml key is checked against the\ntype its reader expects and stored as a TOML boolean or number where the\nreader needs one (`yolo = true`, `max_subagents = 4`); `reasoning_effort`\naccepts the same aliases as `/effort` (#6563). Other dotted writes fail before\nmodifying the file and name the TOML table to edit. For example, set a tools\ntimeout in the file as:\n\n```toml\n[tools]\nuser_input_timeout_seconds = 0\n```\n\n`codewhale config doctor` checks credential presence and endpoint shape, and\nwarns about each config.toml root key that nothing reads: a settings.toml key\nleft in config.toml is named as misplaced, and any other unread key gets a\ndid-you-mean. Keys read by any runtime reader are not reported. The warnings do\nnot fail the check, and a clean result does not validate every runtime setting's\nvalue (#6083, #6563).\n\n## Constitution, project instructions, and repo authority\n\nCodewhale has several instruction surfaces. They are deliberately separate so a\npersonal constitution, repo policy, project instructions, and runtime security\ncontrols do not blur together.\n\n- **Bundled global Constitution** — the compiled base law in the binary. It is\n the default floor for every session.\n- **User-global constitution** — the normal guided setup output. Manage it with\n `/constitution` or `/setup`; Codewhale stores structured data at\n `$CODEWHALE_HOME/constitution.json` (default `~/.codewhale/constitution.json`)\n and renders it into a separate `<codewhale_user_constitution>` prose block.\n This can express preferences and stop conditions, but it does not change\n runtime approval policy, sandbox, shell, network, trust, or MCP permissions.\n- **Repo-local constitution** — optional project policy in\n `.codewhale/constitution.json`, described below.\n- **`AGENTS.md`** — cross-agent **project instructions** (prose). This is the\n canonical file for \"how should an agent work in this repo.\" Run `/init` to\n scaffold one. `CLAUDE.md` and `.claude/instructions.md` are read as\n compatibility fallbacks.\n- **Memory and handoffs** — recalled state. Useful, but lower authority than\n constitutions and project instructions.\n\n### Managing the user-global constitution (`/setup` and `/constitution`)\n\nThe bundled **working agreement** is the safe default and no longer adds a\nrequired first-run screen. Customize it later through `/constitution` or the\nprogressive `/setup` guide. Provider/model readiness, workspace trust, and\nruntime posture stay separate from this guidance.\n\nOn the **Working agreement** (constitution) step:\n\n- **`1`–`6`** tune the guided draft. **`G`** previews it, and **`G`** again\n ratifies and saves a fresh structured `constitution.json`.\n- **`A`** (shown only when a provider is configured) asks your first configured\n model to draft the constitution. Drafting is **not** saving: the draft is\n rendered through the same preview and you still press **`G`** to ratify\n before anything persists.\n- **`K`** keeps your existing loaded constitution unchanged (shown only when a\n valid file is already present).\n- **`U`** (or `/coLine truncated
}
]
},
{
"id": "skills",
"slug": "skills",
"sources": [
{
"path": "docs/SKILLS.md",
"sha256": "2f9b64703036c8c6159c979c9c2f4fbebf2b96577f8081a0b09135c7d78e36e4",
"content": "# Skills Manager\n\nIn the terminal, `/skills` opens **Extensions → Skills**. Enter on a skill opens the dedicated manager, also available directly through `/skills manage`, for existing install, update, remove, and trust operations. `/skill <name>` still activates a skill, and the explicit inspection, remote, sync, and suggestion subcommands remain available.\n\n\n> 阅读简体中文版:[zh_hans/SKILLS.md](zh_hans/SKILLS.md)\n\nSkills are reusable `SKILL.md` instruction packs. Codewhale discovers them from\nseveral roots, but **only Codewhale-owned directories are writable**. The unified\n`/skills manage` manager is the interactive surface for audit and mutation; slash\naliases share the same write path.\n\nFor Claude Code plugin boundaries, see [CLAUDE_PLUGIN_COMPAT.md](CLAUDE_PLUGIN_COMPAT.md).\nFor `skills_dir` and `[skills]` config keys, see [CONFIGURATION.md](CONFIGURATION.md).\n\n## Architecture (four layers)\n\n| Layer | Role |\n| --- | --- |\n| **Root catalog** | Single source of precedence and ownership (`SkillRootCatalog`). |\n| **Audit** | Read-only, unmerged on-disk inventory (status, digest, actions). |\n| **Mutation controller** | Only writer for install / import / update / remove / trust. |\n| **Skills manager view** | TUI: emits events only; never writes files itself. |\n\nRuntime discovery (`SkillRegistry`) still merges skills for the model. Audit\nintentionally does **not** merge — it shows every on-disk copy so conflicts and\nshadowing stay visible.\n\n## Ownership and roots\n\n**Writable (Codewhale-owned)**\n\n| Scope | Path |\n| --- | --- |\n| Project | `<workspace>/.codewhale/skills/` |\n| Global | `~/.codewhale/skills/` |\n\n**Read-only compatible** (discover / import source only — never mutated in place)\n\nExamples: `<workspace>/.agents/skills`, `./skills`, `.claude/skills`,\n`.cursor/skills`, `.opencode/skills`, `~/.agents/skills`, `~/.claude/skills`,\nand similar harness layouts.\n\n**Audit-only (not runtime-active)**\n\n- Flat `<workspace>/skills` is an audit candidate until `[skills] flat_workspace_root = true`; an explicit `skills_dir` can also select it.\n- `.codex/skills` appears in **compatible** audit scans so operators can see it.\n It does **not** join the runtime discovery set.\n\nConfigured `skills_dir` that is not one of the owned Codewhale roots stays\nread-only. Discovery and the manager can list it; mutations still target owned\nproject/global roots only.\n\nWithin each scope, the owned `.codewhale/skills` root wins name collisions.\nProject order is `.codewhale`, `.agents`, `.claude`, `.opencode`, `.cursor`, then\nan opted-in flat `skills` root. Global order is `.codewhale`, `.agents`, `.claude`,\nthen legacy `.deepseek`. Project roots precede global roots. Shadowing warnings\nname both copies, so install and update select the owned copy in that scope.\n\nEvery root inside the workspace — owned, compatible, or a configured\n`skills_dir` that resolves there — loads only once the workspace is trusted\n(`/trust on --save`). Until then discovery names the skipped directories in its\nwarning, and the session's skills directory falls back to the global one.\n\n## Slash commands\n\n| Command | Behavior |\n| --- | --- |\n| `/skills` | Opens Extensions → Skills (owned-only scan, **no network**). |\n| `/skills manage` | Opens the dedicated Skills Manager for audit and mutation. |\n| `/skills <prefix>` | Text list filtered by name prefix. |\n| `/skills inspect` | Text discovery mode, searched directories, and source paths. |\n| `/skills --remote` | Explicit registry listing (network). |\n| `/skills suggest <task>` | Rank up to three remote skills for a task, with matching evidence and an explicit install command (network; no install). |\n| `/skills sync` | Explicit registry → local cache sync (network). |\n| `/skill <name>` | Activate a skill for the next turn. |\n| `/skill install [--project\\|--global] <spec>` | Install via mutation controller. |\n| `/skill update [--project\\|--global] <name>` | Update a managed skill from its registry provenance. |\n| `/skill uninstall [--project\\|--global] <name>` | Remove a managed skill. |\n| `/skill trust [--project\\|--global] <name>` | Write digest-bound advisory trust. |\n\nNotes:\n\n- There is **no** `/skills audit` subcommand. Use the manager (and `c` to toggle\n compatible roots) or `/skills inspect` for discovery details.\n- Bare `/skill install <spec>` (no scope flag) installs into the Codewhale\n **global** owned root.\n- `/skills suggest` only reads the curated registry through the existing\n network policy. It never downloads, trusts, enables, or activates a skill;\n each result gives a separate `/skill install <name>` command for the user to\n choose.\n- If the same name exists in both project and global owned roots, update /\n uninstall / trust require `--project` or `--global`.\n- If a name exists only under a compatible external root, writes are refused;\n import it througLine truncated
},
{
"path": "docs/CLAUDE_PLUGIN_COMPAT.md",
"sha256": "d1c66e79af9ca257d883c503f36a892a5d270326c7e1a79a5322e4b4a7057f24",
"content": "# Claude Plugin Compatibility\n\nCodewhale treats Claude Code skill folders as instruction bundles when they are\nplain `SKILL.md` directories. It does not run Claude Code plugin runtimes.\n\n## Supported\n\n- Workspace or global `.claude/skills/<name>/SKILL.md` directories discovered by\n the normal skill registry.\n- GitHub or tarball installs that contain one selected skill directory such as\n `skills/<name>/SKILL.md`, `.agents/skills/<name>/SKILL.md`,\n `.claude/skills/<name>/SKILL.md`, or a nested package layout ending in\n `skills/<name>/SKILL.md`.\n- Companion files inside the selected skill directory, such as `references/`,\n `examples/`, or scripts that are only used after the skill is explicitly\n loaded and trusted.\n\n## Compatible plugin bundles\n\nSince v0.9.13, `/plugin install` accepts the declarative subset described in\n[Installing plugins](PLUGINS.md): nested `.claude-plugin/plugin.json` metadata,\nroot skills, commands and agent profiles, plus inline MCP declarations or\n`.mcp.json`. Local sources in Claude marketplace catalogs resolve from the\nrepository root outside `.claude-plugin`.\n\nExact `${ENV_NAME}` MCP header references map to Codewhale's environment-backed\ncredentials, including `Authorization: Bearer ${ENV_NAME}`. Literal credential\nvalues and compound header templates are rejected; importing never reads the\nreferenced environment variables.\n\nThe importer uses Codewhale's existing adapters, review hashes and enablement.\nA Claude marketplace's labels or defaults grant no authority. Bundles are not\nscanned from another application's plugin roots or activated automatically.\n\n## Unsupported runtime features\n\nThe importer rejects hooks, LSP declarations, custom MCP file paths, and\n`${CLAUDE_PLUGIN_ROOT}` expansion. It does not run plugin build steps,\nTypeScript agents, dashboard servers, shared plugin state, or token-gated\nservice processes. Claude-specific frontmatter behavior such as `model: inherit`\nis not an additional runtime contract. Remote MCP authentication still follows\nCodewhale's existing plugin credential boundary; installation does not complete\nOAuth or borrow another application's credentials.\n\n`/skill install` remains a separate one-skill operation: it rejects multi-skill\nplugin archives rather than silently selecting one directory and dropping other\ncomponents. Use `/plugin install` for supported bundles, or migrate one explicit\nskill directory when the repository depends on unsupported runtime behavior.\n\nSee [PLUGIN_BUNDLES.md](PLUGIN_BUNDLES.md) for discovery, review and activation.\n"
}
]
},
{
"id": "claude-code",
"slug": "claude-code",
"sources": [
{
"path": "docs/CLAUDE_PLUGIN_COMPAT.md",
"sha256": "d1c66e79af9ca257d883c503f36a892a5d270326c7e1a79a5322e4b4a7057f24",
"content": "# Claude Plugin Compatibility\n\nCodewhale treats Claude Code skill folders as instruction bundles when they are\nplain `SKILL.md` directories. It does not run Claude Code plugin runtimes.\n\n## Supported\n\n- Workspace or global `.claude/skills/<name>/SKILL.md` directories discovered by\n the normal skill registry.\n- GitHub or tarball installs that contain one selected skill directory such as\n `skills/<name>/SKILL.md`, `.agents/skills/<name>/SKILL.md`,\n `.claude/skills/<name>/SKILL.md`, or a nested package layout ending in\n `skills/<name>/SKILL.md`.\n- Companion files inside the selected skill directory, such as `references/`,\n `examples/`, or scripts that are only used after the skill is explicitly\n loaded and trusted.\n\n## Compatible plugin bundles\n\nSince v0.9.13, `/plugin install` accepts the declarative subset described in\n[Installing plugins](PLUGINS.md): nested `.claude-plugin/plugin.json` metadata,\nroot skills, commands and agent profiles, plus inline MCP declarations or\n`.mcp.json`. Local sources in Claude marketplace catalogs resolve from the\nrepository root outside `.claude-plugin`.\n\nExact `${ENV_NAME}` MCP header references map to Codewhale's environment-backed\ncredentials, including `Authorization: Bearer ${ENV_NAME}`. Literal credential\nvalues and compound header templates are rejected; importing never reads the\nreferenced environment variables.\n\nThe importer uses Codewhale's existing adapters, review hashes and enablement.\nA Claude marketplace's labels or defaults grant no authority. Bundles are not\nscanned from another application's plugin roots or activated automatically.\n\n## Unsupported runtime features\n\nThe importer rejects hooks, LSP declarations, custom MCP file paths, and\n`${CLAUDE_PLUGIN_ROOT}` expansion. It does not run plugin build steps,\nTypeScript agents, dashboard servers, shared plugin state, or token-gated\nservice processes. Claude-specific frontmatter behavior such as `model: inherit`\nis not an additional runtime contract. Remote MCP authentication still follows\nCodewhale's existing plugin credential boundary; installation does not complete\nOAuth or borrow another application's credentials.\n\n`/skill install` remains a separate one-skill operation: it rejects multi-skill\nplugin archives rather than silently selecting one directory and dropping other\ncomponents. Use `/plugin install` for supported bundles, or migrate one explicit\nskill directory when the repository depends on unsupported runtime behavior.\n\nSee [PLUGIN_BUNDLES.md](PLUGIN_BUNDLES.md) for discovery, review and activation.\n"
},
{
"path": "docs/CONFIGURATION.md",
"sha256": "3dbae94838073e457a57abd5ec59d1b0ef5be5dc0ae358f515f6e5b6ffe3b23f",
"content": "# Configuration\n\ncodewhale reads configuration from a TOML file plus environment variables.\nAt process startup it may also load literal built-in-provider credentials from\na workspace-local `.env` file. Use the tracked `.env.example` as the template;\ncopy it to `.env`, then add only credential values.\n\nA workspace is not configuration authority. Codewhale therefore ignores\nconfig/profile/home paths, provider/model/base-URL routing, MCP/plugin state,\napproval/sandbox/shell posture, executable paths, runtime settings, and every\nother non-credential `.env` entry. Variable expansion is rejected so a\nrepository cannot substitute an ambient secret into a credential value. Use\n`config.toml`, CLI flags, or values exported by the launching shell for those\nexplicit control-plane settings. `.env` is read from a stable regular-file\nhandle, is capped at 1 MiB, and symbolic links, reparse points, and multiply\nlinked files are rejected.\n\n## Reading and checking configuration from the CLI\n\n`codewhale config get <key>` reads scalar keys, whole tables such as `tools`,\nand nested paths such as `tools.user_input_timeout_seconds`. Displayed tables\nand nested values apply the same recursive credential redaction as `config dump`.\n\n`config set` supports its named scalar keys and the provider, route, and\nnotification commands. It refuses a key that nothing reads and suggests the\nnearest real key (`config set calm_mod on` names `calm_mode`). A settings.toml\nkey such as `calm_mode` or `tool_collapse` is validated and written to the\nuser-global settings.toml, not config.toml; `config get` reads it back from\nthere even when an old config.toml copy (which nothing reads) is still present,\nand names that copy so you can `config unset` it. Settings keys have no project\nscope, so `--project` refuses them. A config.toml key is checked against the\ntype its reader expects and stored as a TOML boolean or number where the\nreader needs one (`yolo = true`, `max_subagents = 4`); `reasoning_effort`\naccepts the same aliases as `/effort` (#6563). Other dotted writes fail before\nmodifying the file and name the TOML table to edit. For example, set a tools\ntimeout in the file as:\n\n```toml\n[tools]\nuser_input_timeout_seconds = 0\n```\n\n`codewhale config doctor` checks credential presence and endpoint shape, and\nwarns about each config.toml root key that nothing reads: a settings.toml key\nleft in config.toml is named as misplaced, and any other unread key gets a\ndid-you-mean. Keys read by any runtime reader are not reported. The warnings do\nnot fail the check, and a clean result does not validate every runtime setting's\nvalue (#6083, #6563).\n\n## Constitution, project instructions, and repo authority\n\nCodewhale has several instruction surfaces. They are deliberately separate so a\npersonal constitution, repo policy, project instructions, and runtime security\ncontrols do not blur together.\n\n- **Bundled global Constitution** — the compiled base law in the binary. It is\n the default floor for every session.\n- **User-global constitution** — the normal guided setup output. Manage it with\n `/constitution` or `/setup`; Codewhale stores structured data at\n `$CODEWHALE_HOME/constitution.json` (default `~/.codewhale/constitution.json`)\n and renders it into a separate `<codewhale_user_constitution>` prose block.\n This can express preferences and stop conditions, but it does not change\n runtime approval policy, sandbox, shell, network, trust, or MCP permissions.\n- **Repo-local constitution** — optional project policy in\n `.codewhale/constitution.json`, described below.\n- **`AGENTS.md`** — cross-agent **project instructions** (prose). This is the\n canonical file for \"how should an agent work in this repo.\" Run `/init` to\n scaffold one. `CLAUDE.md` and `.claude/instructions.md` are read as\n compatibility fallbacks.\n- **Memory and handoffs** — recalled state. Useful, but lower authority than\n constitutions and project instructions.\n\n### Managing the user-global constitution (`/setup` and `/constitution`)\n\nThe bundled **working agreement** is the safe default and no longer adds a\nrequired first-run screen. Customize it later through `/constitution` or the\nprogressive `/setup` guide. Provider/model readiness, workspace trust, and\nruntime posture stay separate from this guidance.\n\nOn the **Working agreement** (constitution) step:\n\n- **`1`–`6`** tune the guided draft. **`G`** previews it, and **`G`** again\n ratifies and saves a fresh structured `constitution.json`.\n- **`A`** (shown only when a provider is configured) asks your first configured\n model to draft the constitution. Drafting is **not** saving: the draft is\n rendered through the same preview and you still press **`G`** to ratify\n before anything persists.\n- **`K`** keeps your existing loaded constitution unchanged (shown only when a\n valid file is already present).\n- **`U`** (or `/coLine truncated
}
]
},
{
"id": "plugins",
"slug": "plugins",
"sources": [
{
"path": "docs/PLUGINS.md",
"sha256": "ef3932ff895ae6482a83820f997c4f5b5383a11d9750773c77b7868e2acd4309",
"content": "# Installing plugins\n\n> 阅读简体中文版:[zh_hans/PLUGINS.md](zh_hans/PLUGINS.md)。\n\nTo create a bundle, start with [Write your first Codewhale plugin](PLUGIN_AUTHORING.md)\nand its runnable Skills example.\n\nThis is the walkthrough for the `/plugin install` on-ramp (v0.9.4, #5182).\n[PLUGIN_BUNDLES.md](PLUGIN_BUNDLES.md) remains the contract for the bundle\nformat (`plugin.json`, compatible `kimi.plugin.json` or\n`.claude-plugin/plugin.json`, or legacy `plugin.toml`), discovery, validation, and\nthe trust/enable lifecycle — this document covers how bits get onto disk in\nthe first place.\n\n`/plugin suggest <task>` is a local, read-only companion: it ranks already\ninstalled bundles (name, keywords, description, bundled skill names, declared\nhosts) and any marketplace catalogs you have added with `/plugin marketplace add`.\nIt explains the match and gives the next review, enable, or catalog-install\nstep, but never installs, trusts, or enables a bundle on its own.\n\n## How Codewhale offers plugins\n\nCodewhale is helpful about plugins, not pushy. The rules:\n\n- **One proactive surface.** Sending a task can show one quiet toast when the\n prompt matches an installed-but-idle plugin or a catalog candidate you do\n not have yet, for example `/plugin trust supabase` or\n `/plugin marketplace install <catalog> supabase`. Nothing appears while you\n type, and nothing is appended to your message to advertise plugins.\n- **One switch.** With `contextual_tips` off, no plugin guidance appears\n anywhere. Required notices and your own `/plugin` commands still work.\n- **One budget.** Plugin offers share the per-session guidance budget with\n other tips. In the interactive TUI the model can call\n `request_plugin_install` once per session to ask you to review a plugin the\n task needs; a second call fails. Exec, ACP, and runtime-API sessions do not\n get the tool.\n- **Built-ins are never advertised.** Bundled plugins such as Computer Use\n appear only in `/plugin list` and Extensions.\n- **Specific terms only.** Generic words (accessibility, browser, chrome,\n docs, screenshot, web, wiki, …) never trigger an offer. The matcher and the\n marketplace's `check-marketplace.mjs` share one stoplist.\n- **Only what runs here.** Plugins whose `when.os` excludes this OS are not\n offered.\n- **Review before acting.** A model-requested row offers Review. Its button\n opens the existing Extensions inventory: Plugins for an installed bundle,\n Marketplace for a suggestion that is not installed. Nothing is installed,\n trusted, or enabled by that click. Choose the inventory's explicit action;\n trust still reviews the exact installed content before activation.\n- **Reversible dismissal.** Esc clears a non-empty draft first, then hides the\n row for this session only. \"Don't suggest again\" is the explicit,\n persisted choice. `/plugin dismissals` lists both kinds, and\n `/plugin dismissals reset [<name>]` lets suggestions offer a plugin again.\n- **Discovery is passive.** Find new plugins in these docs,\n `/plugin marketplace list`, Extensions, and the browser guide below.\n\nCodewhale does not invent a remote plugin URL; missing plugins are suggested\nonly from catalogs you added. On-disk bundle changes still toast\n`/plugin reload` on send and between turns.\n\n## Browser: pick one\n\nSeveral options can drive a browser. They differ in whose browser it is and\nwhat it can see.\n\n| Option | Whose browser | Good for |\n| --- | --- | --- |\n| `chrome-devtools` MCP (`/mcp recommendations`) | A Chrome it drives, which can include signed-in pages | DevTools-level inspection and performance work |\n| Playwright MCP (`/mcp recommendations`) | A fresh, isolated profile with `--isolated` | Scripted flows and testing without your identity |\n| Computer Use `browser_*` tools (bundled, off until reviewed) | One it launches, in a profile of its own | Browser steps inside a wider desktop task |\n| Chromewhale (developer preview, `codewhale-hq/codewhale-plugin-marketplace`) | Yours, already open, in your own Chrome profile; load unpacked | Reading or acting on the tab you are looking at, one granted site at a time |\n\nNone of these is offered to you proactively. Add the one that fits the job.\n\n## Sources\n\n`codewhale install <spec>` and `/plugin install <spec>` use the same installer.\nThe shell entry does not start a model or require model credentials. Both keep\nbundles disabled and untrusted until you explicitly review and enable them.\n\n```sh\ncodewhale install git:github.com/example/plugin@v1.0.0\ncodewhale install npm:@example/plugin@1.0.0\ncodewhale install ./local-plugin\n```\n\nGit shorthand supports GitHub archives only; refs must be a single safe segment.\nUse the existing HTTPS archive URL plus `#path=...` for a nested bundle.\nNpm requires an exact version and a native plugin manifest in the tarball.\nNo git hooks, npm lifecycle scripts, dependency installation oLine truncated
},
{
"path": "docs/PLUGIN_BUNDLES.md",
"sha256": "7138da9a999fc8e94222a2cffae3b9ebdeb41ed19ab8941d24ff57a96d39d086",
"content": "# Plugin bundles\n\n> 阅读简体中文版:[zh_hans/PLUGIN_BUNDLES.md](zh_hans/PLUGIN_BUNDLES.md)。\n\nCodewhale supports a deliberately small plugin-bundle boundary. The boundary\nwas drawn in v0.9.1 and is extended deliberately in v0.9.10: a bundle may\ncontribute declarative Skills, MCP configuration, Commands, Agent profiles,\nand Hooks through Codewhale's existing engines. Unsupported declarations stay\ninventoried instead of disabling a mixed bundle. Discovery alone never\nexecutes, enables, trusts, downloads, updates, or installs anything.\n\nThis document owns the bundle formats, discovery,\nvalidation, and the trust/enable/runtime contract. [PLUGINS.md](PLUGINS.md)\nowns how bits get onto and off disk — the `/plugin install`, `update`,\n`uninstall`, and `suggest` on-ramp added in v0.9.4 (#5182). Compatible Claude Code bundles use the same native adapters; their supported subset is\n[CLAUDE_PLUGIN_COMPAT.md](CLAUDE_PLUGIN_COMPAT.md).\nFor a runnable native example and explicit OpenCode/DSH data conversion, see\n[Write your first plugin](PLUGIN_AUTHORING.md).\n\n## Discovery and precedence\n\nCodewhale scans only its own roots, looking in each `<name>/` directory for a\nmanifest named `plugin.json` (the native Agent Plugins v1.0.0 format, since\nv0.9.4), `kimi.plugin.json` (the compatible Kimi Skills/MCP subset, since\nv0.9.8), `plugin.toml` (the legacy Codewhale format, still fully readable), or\n`.claude-plugin/plugin.json` (the compatible Claude subset, since v0.9.13):\n\n- User: `~/.codewhale/plugins/<name>/`\n- Workspace: `<workspace>/.codewhale/plugins/<name>/`\n\nA bundle that publishes multiple formats is read through `plugin.json` first,\nthen `kimi.plugin.json`, then the legacy `plugin.toml`, then\n`.claude-plugin/plugin.json`.\nComputer Use ships as a built-in bundle; it still requires review and\nenablement before activation. The internal precedence order is\nbuilt-in, user, then workspace; the first bundle with a given name wins. This\nprevents a repository from shadowing an explicitly installed user bundle.\nSymbolic-link roots, manifests, component paths, and nested component files\nfail closed.\n\nThe embedded Computer Use files are materialized under\n`$CODEWHALE_HOME/builtin-plugins/snapshots/computer-use-<bundle-digest>/computer-use`.\nEach process captures only its own embedded digest's discovery root. Concurrent\nbuilds therefore keep separate, complete source trees; publishers never delete\nor replace an existing snapshot. Reuse checks every embedded byte, directory\nentry, file type, executable flag, and the stamp. A partial or altered snapshot\nis rejected without repair. Interrupted private staging directories are not\ndiscovered or reused.\n\nThe existing path-bound plugin identity and trust rules apply: identical embedded\nbytes at the same home reuse the same identity; changed bytes require a fresh\nreview and enablement. Moving from the older mutable\n`builtin-plugins/computer-use` layout also requires one fresh review. Legacy\nbundles and receipts remain intact for running older binaries; no trust is\nmigrated. Diagnostics do not create a missing Codewhale home.\nThe selected home may itself be a symlink: its resolved directory is pinned\nbefore creating any built-in paths. Links in the owned built-in cache paths\nstill fail closed.\n\nNew user and workspace bundles are always untrusted and disabled. Discovery is\nread-only and does not inspect any other application's extension or credential\ndirectories: ambient roots such as `.claude/plugins` or `.cursor/plugins` are\nnever scanned.\n\nPre-v0.9.1 `overrides.json` enablement was intentionally not imported as\ntrust; every bundle activates only through the content-hash and\n`codewhale-plugin-capabilities-v3` activation-policy review below.\n\n## Manifest\n\nAll supported encodings parse into the same internal manifest, so validation, hashing,\nreview, and runtime behavior are identical downstream. On-disk auto-migration\nbetween them is deliberately not performed; `/plugin export <name>\n<target-dir>` publishes a loaded bundle as a spec-valid Agent Plugins v1.0.0\ndirectory without modifying the installed one.\n\n### `plugin.json` (Agent Plugins v1.0.0)\n\nThe standard's manifest root is closed: `$schema`, `name`, and the optional\nwell-known fields (`version`, `description`, `author`, `homepage`,\n`repository`, `license`, `keywords`, `extensions`). An unknown root key is a\nparse error. Client-specific data lives under `extensions`, keyed by\nreverse-domain namespace: unknown vendor namespaces are ignored, never\nrejected — that is what lets a bundle authored for another client load here —\nwhile unknown keys inside Codewhale's own `extensions[\"net.codewhale\"]`\nnamespace are rejected rather than silently dropped.\n\nNames follow the standard's rule: 1–64 lowercase ASCII letters, digits, or\ninternal single `-`/`.`, starting and ending alphanumeric, never `--` or `..`.\nA `skills/` dirLine truncated
},
{
"path": "docs/EXTENSIONS.md",
"sha256": "a1c2ff519b0896aec3c42c3bf277e688392cfaa5d8c3e0380d99631d3c65fb86",
"content": "# Writing an extension tool or command\n\nThe experimental TypeScript extension host runs reviewed plugin code in a\nshared Node process (or, as an opt-in, Bun). Rust still owns sessions, tool admission, approval and\nexecution. Extensions currently contribute tools and slash commands; they\ncannot provide an approval service, run a second agent loop or replace\nbuilt-in tools or commands.\n\n## Quick start\n\nStart with [hello-extension](examples/plugins/hello-extension/hello.mts) and its\n[plugin.json](examples/plugins/hello-extension/plugin.json). The example is\nexecuted unchanged by the host tests. It returns a greeting and does not read\nfiles or use the network.\n\n1. Explicitly enable `[features] extension_host = true` in your configuration,\n or start Codewhale with `codewhale --enable extension_host` (the flag goes\n before any subcommand).\n2. Install the example's directory using `/plugin install <local-directory>`.\n3. Run `/plugin validate hello-extension`, then `/plugin show hello-extension`.\n4. Run `/plugin enable hello-extension` to open its content/capability review.\n Read the review and personally run its exact `/plugin trust <token>` command,\n then enable the plugin. Trust alone does not execute the code.\n5. Ask Codewhale to use `hello_greet`. The tool follows the normal approval gate.\n6. Run `/hello-greet Codewhale`. The command runs when you type it, and shows\n its answer in the transcript with its origin, `extension:hello-extension`.\n\nAn authoring agent should stop after installation and validation and present\nthe review to the person. Do not trust or enable a bundle automatically.\n\n## Locations, installation and trust\n\nUser bundles live under `~/.codewhale/plugins/`; workspace bundles live under\n`<workspace>/.codewhale/plugins/`. New bundles use Agent Plugins v1.0.0\n`plugin.json`. Declare `extensions[\"net.codewhale\"].native.path` as one regular\n`.mjs`, `.js` or `.mts` file inside the bundle. Directories and other extensions\nfail validation when the host is enabled. With the flag off, native entries\nremain inventory-only.\n\nA plugin may split its code across several entries with `native.paths` (up to\n64, alone or beside `path`). They are activated in the order declared, as the\nfibers of one plugin: they share one owner, so one disable, review change or\ncrash tears all of them down together. Each entry is a separate module with its\nown `apply`, and tool and command names must be unique across them. If an entry\nfails to activate (throws, requires a service the host does not provide, or has\na registration refused), only that entry is withdrawn: entries that already\nactivated stay registered, later entries still activate, and the plugin fails\nonly when no entry activates. Listing the same file twice is one entry.\n\n## Runtime\n\n`[extension_host] runtime` selects what runs the host. Node is the default.\nBun is an opt-in: it is qualified on macOS only, and becomes the default only\nafter an explicit, recorded cutover.\n\n```toml\n[extension_host]\nruntime = \"node\" # default: Node only\n# runtime = \"bun\" # Bun only; fails rather than falling back to Node\n# runtime = \"auto\" # Bun >= 1.4.0 if one is found and starts, otherwise Node\n# bun = \"~/.bun/bin/bun\" # the only Bun tried when set\n# node = \"/opt/homebrew/bin/node\" # the only Node tried when set\n# mcp_backend = \"host\" # experimental SDK backend; default is \"rust\"\n```\n\n`mcp_backend = \"host\"` selects the pinned MCP SDK independently of\n`[features] extension_host`. That feature controls optional Native extensions;\nselecting Host MCP does not activate them. The SDK for existing stdio, HTTP and legacy SSE server connections in a separate\nbuiltin host process. Rust retains process/network authority, credential\nresolution, catalog admission, tool approval and cancellation. HTTP/SSE uses\nRust's guarded HTTP client; the SDK receives opaque session selectors and\nexact operation grants. Request IDs remain the Rust client's strings through\nan adapter bound to each grant. Explicit Host selection never falls back to\nRust or replays an uncertain operation. The default remains `\"rust\"` while\nrecorded transport parity is qualified. The Host path uses the same Rust\nGET session preflight and bounded reactive OAuth refresh as the default\nbackend. An explicit incompatible HTTP response can negotiate the real SDK\nSSE transport only with a fresh exact Rust operation grant; a stale-session\nrefusal remains a typed Rust recovery decision. Credentials, configured URLs,\nOAuth browser/login operations and Computer Use decision keys stay in Rust.\nBoth backends run against the same recorded MCP goldens. Passing that suite\nand the actual broker acceptance tests is required before any default cutover.\nThe default also requires the platform isolation and measured Phase 3 gates\nin Ops CURRENT_DECISIONS §26. The native Rust protocol adapters remain for one\nLine truncated
}
]
},
{
"id": "runtime-api",
"slug": "runtime-api",
"sources": [
{
"path": "docs/RUNTIME_API.md",
"sha256": "8099f51c887ec1d4a35122c0057f584b05bc9a665ae82f3b74a1992a7c849732",
"content": "# Codewhale Engine Runtime API & Integration Contract\n\n> 阅读简体中文版:[zh_hans/RUNTIME_API.md](zh_hans/RUNTIME_API.md)。\n\n`codewhale app-server` exposes the [Codewhale Engine](ARCHITECTURE.md) through\nits canonical local Runtime API and control plane.\nLocal SDKs, mobile/remote-control clients, and editor integrations talk to it\ninstead of screen-scraping terminal output. It serves the full HTTP/SSE runtime\nAPI (`/v1/*`), a JSON-RPC control transport over stdio, and the phone-friendly\nmobile page. `codewhale doctor --json` provides machine-readable health, and\n`codewhale serve --acp` speaks the Agent Client Protocol over stdio for editors\nsuch as Zed.\n\n`codewhale serve --http` / `serve --mobile` remain as **compatibility aliases**\nfor `codewhale app-server --http` / `--mobile`; both launch the identical\nserver. New integrations should target `app-server`.\n\n`codewhale exec` is the separate one-shot headless worker path (stream-json,\nfleet worker subprocess, CI primitive). It is not part of this API, but it\nshares the same runtime, provider/model resolution, permission profiles, and\nevent vocabulary.\n\nThis document is the stable integration contract for native workbench\napplications (and other local supervisors) that embed the Codewhale Engine.\n\n## Architecture\n\n```\nlocal supervisor / SDK / automation harness\n │\n ├─ codewhale app-server --http → HTTP/SSE runtime API (/v1/*) [canonical]\n ├─ codewhale app-server --mobile → runtime API + mobile control page\n ├─ codewhale app-server --stdio → JSON-RPC control transport over stdio\n ├─ codewhale app-server --socket → same JSON-RPC over a unix domain socket (desktop daemon)\n ├─ codewhale doctor --json → machine-readable health & capability\n ├─ codewhale serve --acp → ACP stdio agent for editors such as Zed\n ├─ codewhale serve --mcp → MCP stdio server\n ├─ codewhale serve --http/--mobile → legacy aliases for `app-server --http/--mobile`\n └─ codewhale exec [args] → one-shot headless worker (stream-json)\n```\n\nThe engine runs as a local-only process. All APIs bind to `localhost` by\ndefault. No hosted relay, no provider-token custody, no secret leakage.\n\nFor the read-only record of what a thread or turn did, see\n[`docs/RECEIPTS.md`](RECEIPTS.md): `codewhale receipts` on the CLI and the\n`/receipt` routes under **Threads** below.\n\n## Runtime API entrypoints\n\n| Entry | Transport | Use |\n|---|---|---|\n| `codewhale web [--port 7878]` | HTTP/SSE on `127.0.0.1:7878` + embedded client | First-class loopback-only browser client; opens the default browser |\n| `codewhale app-server --http` | HTTP/SSE on `127.0.0.1:7878` | Full `/v1/*` runtime API (canonical) |\n| `codewhale app-server --mobile` | HTTP/SSE on loopback + `/mobile` | Runtime API + local mobile control page |\n| `codewhale app-server --stdio` | JSON-RPC 2.0 over stdio | Local SDK / control probe (no listener) |\n| `codewhale app-server --socket [--socket-path P]` | JSON-RPC 2.0 over a `0600` Unix domain socket (macOS/Linux) or an owner-only named pipe (Windows) | Desktop daemon: multi-client, kernel peer identity checked, `daemon/attach` claim handshake. Windows native-app qualification remains open. |\n| `codewhale app-server` | HTTP on `127.0.0.1:8787` | Legacy in-process app-server (`/healthz`, `/thread`, `/app`, `/prompt`); background jobs are `GET /v1/jobs` on the Runtime API; `/prompt` and `/thread` messages execute real turns via the runtime bridge. There is no direct `/tool` route: tools run only inside Engine turns, under the Engine's tool catalog and approval posture. This legacy server does not surface approvals: its bridge forwards only text deltas and the turn's completion, and it has no decision route, so an approval-gated call waits unanswered. Drive approval-gated work through the Runtime API (`/v1/threads/*` events and `POST /v1/approvals/{approval_id}`) |\n| `codewhale serve --http` / `--mobile` | same server as `app-server --http`/`--mobile` | Compatibility aliases |\n\n`app-server --http` and `--mobile` launch the same mature runtime API server\nhistorically reached through `serve --http` — no routes or behavior changed, so\nevery endpoint documented below is identical across both entrypoints. The\nruntime API token is read from `--auth-token`, then `CODEWHALE_RUNTIME_TOKEN`,\nthen `DEEPSEEK_RUNTIME_TOKEN`; use `--insecure-no-auth` only with a loopback\nbind. The `serve` compatibility aliases keep their `--insecure` flag.\nThe legacy in-process `codewhale app-server` also requires an explicit\n`--auth-token` or `CODEWHALE_APP_SERVER_TOKEN` before binding a non-loopback\nhost; its generated one-time `cwapp_*` token is loopback-only.\n\nDevice tokens minted by the master through `POST /v1/auth/client-tokens`\nhave an immutable `intent`: `Line truncated
}
]
},
{
"id": "web",
"slug": "web",
"sources": [
{
"path": "docs/WEB.md",
"sha256": "6235bee74db77a00625539fc5e3a243b6cb2ed4fe7788b3337c03c3c3eb8037b",
"content": "# Local browser client\n\n> 阅读简体中文版:[zh_hans/WEB.md](zh_hans/WEB.md)。\n\n`codewhale web` opens Codewhale's embedded browser client over the canonical\nRuntime API. It is a local surface: the server always binds to\n`127.0.0.1`, cannot be rebound to a LAN address, and cannot run with Runtime\nauthentication disabled.\n\n## Start it\n\nFrom the workspace Codewhale should operate in, run:\n\n```bash\ncodewhale web\n```\n\nThe default address is `http://127.0.0.1:7878`. To avoid a local port\ncollision, choose another loopback port:\n\n```bash\ncodewhale web --port 8788\n```\n\nCodewhale starts the Runtime API, serves the dependency-free client embedded\nin the installed binary, prints a single-use launch URL, and asks the operating\nsystem to open that URL in the default browser. If the browser does not open,\nuse the printed URL within ten minutes. Stop the process with `Ctrl+C`; the\nbrowser session ends with it.\n\n## What the browser can do\n\nThe embedded client provides a responsive thread and search rail, Runtime-owned\nsession facts, transcript and tool receipts, and a composer. It can create,\nselect, rename, and archive threads; start or steer turns; interrupt work;\nresolve approvals; and answer Runtime user-input requests.\n\nThe browser is another view of the same local Runtime. It does not create a\nsecond cloud account, copy provider credentials into browser storage, or\nweaken the configured approval and sandbox policies.\n\n## Authentication boundary\n\nThe browser-launch URL contains a random, short-lived, one-time bootstrap\ncapability. It never contains the Runtime bearer token. A loopback request\nexchanges the capability for an `HttpOnly`, `SameSite=Strict`, process-local\nsession cookie and immediately invalidates the capability.\n\nReused, expired, malformed, and non-loopback bootstrap attempts fail closed.\nThe Runtime token is not placed in rendered HTML, browser storage, URL\nqueries or fragments, or browser-launch arguments. The one-time bootstrap\nvalue is printed in the local terminal and briefly passes through the operating\nsystem's browser launcher. It is single-use and expires after ten minutes, but\na hostile process already running as the same OS user remains inside the local\ntrust boundary.\n\nCookie-authenticated state-changing requests must also present the exact\nlocal web origin. Cross-origin browser requests are rejected. Existing\nexplicit bearer and Runtime-token-header clients retain their normal Runtime\nAPI behavior.\n\n## Local means local\n\n`codewhale web` accepts only `--port`; there is no `--host` or insecure-auth\noption on this command. Do not treat it as a public website or expose its port\ndirectly through router forwarding, a public reverse proxy, or a tunnel.\n\nThe separate `codewhale app-server --mobile` and `--http` modes have different\ndeployment and authentication contracts. Read [RUNTIME_API.md](RUNTIME_API.md)\nbefore operating either one, especially before selecting a non-loopback bind.\n\n## Troubleshooting\n\n- If port `7878` is occupied, pass an unused `--port` value.\n- If the browser does not open, copy the printed single-use bootstrap URL into\n a browser on the same machine within ten minutes. Start `codewhale web` again\n if that URL has already been used or expired.\n- If the page loads but a provider is unavailable, inspect `codewhale doctor`\n and `/provider`; the web command does not configure or move provider\n credentials.\n- If a session expired, stop and restart `codewhale web` to mint a new\n process-local session. Reusing an old bootstrap URL is expected to fail.\n\nFor integration endpoints, headers, events, and the complete web-session\ncontract, see [RUNTIME_API.md](RUNTIME_API.md).\n"
}
]
},
{
"id": "computers",
"slug": "computers",
"sources": [
{
"path": "docs/GUIDE.md",
"sha256": "070147fc19193df10e096ff78b32fbb5f775de3f126c0d211c375f50bcd2111e",
"content": "# Codewhale User Guide\n\nThis guide is for your first hour with Codewhale. It explains the main\nworkflow, the important safety controls, and where to go next when you need a\ncomplete reference.\n\nCodewhale has deeper reference documents for installation, configuration,\nproviders, modes, keybindings, tools, and operations. Use this page as a guided\nwalkthrough, then follow the \"Next\" links when you need every option.\n\n## 1. Welcome to Codewhale\n\nCodewhale is a terminal coding agent. You run it from a workspace, give it a\ntask, and it can use structured tools to inspect files, run commands, edit\ncode, and report back with evidence.\n\nThe important difference from a normal chat model is that Codewhale is built\naround a harness:\n\n- It keeps the active workspace and session visible.\n- It routes each turn through explicit modes and approval rules.\n- It shows tool calls in the transcript instead of hiding the work.\n- It can preserve sessions, fork conversations, and continue later.\n- It can run sub-agents for focused background work.\n\nYou can use Codewhale for small questions:\n\n```text\nExplain the authentication flow in this repository.\n```\n\nYou can also use it for multi-step work:\n\n```text\nFind the failing validation path, propose a fix, and wait for my approval\nbefore editing files.\n```\n\nFor a new repository, start conservatively. Ask Codewhale to explore and plan\nbefore asking it to change files. That gives you a reviewable path and makes it\neasier to catch wrong assumptions early.\n\nNext: [ARCHITECTURE.md](ARCHITECTURE.md) explains the internal harness and\nruntime model.\n\n## 2. First Launch\n\nFor a new macOS or Linux installation, use the official GitHub release.\nThe installer verifies the release checksums and provides the same runtime\nunder the `codewhale` and `codew` command names:\n\n```bash\ncurl -fsSL https://codewhale.net/install.sh | sh\n```\n\nWindows users should choose the matching installer or archive from\n[GitHub Releases](https://github.com/codewhale-hq/CodeWhale/releases/latest).\nFor an existing direct install, use `codewhale update --check`, then\n`codewhale update`. npm and Cargo remain secondary packaging routes; Cargo\nalso supports source builds where a compatible prebuilt is unavailable.\nFor occupied directories, package-managed installs, and PATH setup, follow\n[the installation and migration guide](INSTALL.md#recommended-official-github-releases).\nAndroid/Termux uses its own [preview archive or source-build path](INSTALL.md#android--termux-arm64).\n\nDocker is also available when you want an isolated runtime. The published\nimage is currently 0.10.0; to test current `main`, [build it from source](DOCKER.md#building-locally).\n\n```bash\ndocker volume create codewhale-home\ndocker run --rm -it \\\n -e DEEPSEEK_API_KEY=\"$DEEPSEEK_API_KEY\" \\\n -v codewhale-home:/home/codewhale/.codewhale \\\n -v \"$PWD:/workspace\" \\\n -w /workspace \\\n ghcr.io/hmbown/codewhale:latest\n```\n\nOnce the install directory is on PATH, launch Codewhale from the repository or\ndirectory you want it to work in:\n\n```bash\ncodewhale\n```\n\nFor the default GitHub installer destination, you can use\n`\"$HOME/.local/bin/codewhale\"` until that directory is on PATH.\n\nOn first launch, Codewhale opens the composer, even with no key or route.\nWith no key or route, workspace trust is asked once a provider is connected;\notherwise only when the folder requires a decision. A provider is asked for\nwhen you send your first message: the message stays in the box while you sign\nin or use your own key, and a local model is offered only when a local Ollama\nserver answers. The provider step also has an explicit offline route.\n\nEverything optional stays available after that. Use `/setup` for the\nprogressive setup and repair guide, `/settings` for the full typed editor, and\n`/constitution` when you want your own constitution on top of the bundled one.\nThe localized telemetry choice appears only after the workspace is ready and\ndoes not block the composer.\n\nDeepSeek is the default provider. If you want to configure its key before or\nafter the first launch, the most direct setup path is:\n\n```bash\ncodewhale auth set --provider deepseek\n```\n\nYou can also provide a key through the environment:\n\n```bash\nexport DEEPSEEK_API_KEY=\"your-key\"\ncodewhale\n```\n\nNew Codewhale config is stored under `~/.codewhale/config.toml`. Legacy\n`~/.deepseek/config.toml` files are still supported for users migrating from\nthe old name.\n\nUse `/constitution` to review or change standing guidance. After setup, run a\ndoctor check:\n\n```bash\ncodewhale doctor\n```\n\nUse the JSON form when you need a machine-readable report for an issue:\n\n```bash\ncodewhale doctor --json\n```\n\nBoth forms are offline by default. They report structural configuration and\nliteral unknown/not-probed credential states without loading workspace `.env`\ncredentials, openiLine truncated
},
{
"path": "docs/CODEWHALE_AGENT.md",
"sha256": "1d10dd28ce67c87eba7cc0fbc6fe8511ed56b93fcc793466ef76269e6cc698ed",
"content": "# Codewhale Agent — one identity, many surfaces\n\n\"Codewhale Agent\" is one product identity with many transport surfaces.\nThis page is the identity map: what each surface is, where each lives, and\nthe rules that keep them one product instead of several.\n\n## The one identity\n\n| Surface | Identity object | Where it lives | State |\n|---|---|---|---|\n| GitHub PR review | GitHub App bot `codewhale-agent[bot]` | GitHub org settings; repo variable `CODEWHALE_APP_ID` + secret `CODEWHALE_APP_PRIVATE_KEY` | `codewhale review --pr N --post` ships with the `codewhale-review.yml` workflow; it no-ops green until the App is configured (founder-gated), then posts as the App instead of the workflow token. Posting is always opt-in via `--post`. |\n| Commit co-author | `.github/AUTHOR_MAP` | repo | existing; harvested co-author credit lands in the contributor graph |\n| Chat channels | per-user bot registration bound to a Codewhale membership | control-plane `services/control-plane/src/integrations/chat/` BotGateway and adapters; contracts in `packages/contracts` | Source includes Telegram and Slack bot pairing and commands. Default read-only command allowlist; opt-in write verbs; approve/deny keyboards route as permission decisions. Availability depends on the deployed gateway and configured bot credentials. |\n\nSlack bot commands control Codewhale; they do not give an agent tools to search\nor read a Slack workspace. The Slack bot requires a user-managed Slack app,\ncredentials and webhook setup. Hosted Slack delivery and a real authenticated\nSlack task have not been qualified, so this source implementation is not a\nready-to-use Slack integration claim. External Slack tools require a separately\nconfigured and authenticated MCP server or API integration.\n\n## Rules that make it one identity\n\n- Every surface is I/O around the single `Engine::run_turn`\n (`crates/tui/src/core/engine/turn_loop.rs`). No surface gets its own\n engine or turn loop.\n- Every surface authenticates to the same Codewhale membership\n (`codewhale login` account session). Membership gates cloud agents;\n provider brands stay internal and invisible.\n- Approvals from any surface route back as permission decisions into the\n same engine. A bare message never executes a gated action.\n- Every command and approval is audited, on every channel.\n- All surfaces are FREE. Rate limits are anti-abuse only. There is no\n per-channel fee, message metering, team gating, or trial timer — and a\n billing hook on a channel feature is forbidden by the money model.\n\n## Naming\n\n- Product: Codewhale. Agent surface: \"Codewhale Agent\".\n- Bot handle wherever it can be chosen: `codewhale-agent`.\n- The agent speaks as \"Codewhale cloud agent\" — never as a provider brand.\n\n## Channel contract\n\nPer-channel command allowlists (default read-only: `status`, `jobs`,\n`receipts`, `help`; opt-in: `new task`, `approve`, `deny`), inline\napprove/deny keyboards routed as permission decisions, `assistant_changes`\nreply mode (message only when something changed), per-channel message\nformat adapters (including Telegram markdown and Slack blocks in source),\nquiet hours + digest, automation output routable\nto any paired channel, one pairing code bound inside the authenticated\napp, unbind revokes instantly.\n\nWeChat note: personal-WeChat automation is **not supported** —\nreverse-engineered protocols get users banned. Official 公众号/服务号 APIs\nare the only acceptable path and are still under assessment.\n\n## Pointer\n\nChannel contracts live in `packages/contracts` (CWC repo); the gateway and\nadapters live in `services/control-plane/src` (CWC repo). The GitHub\nsurface lives in `.github/workflows/codewhale-review.yml` here.\n"
}
]
},
{
"id": "troubleshooting",
"slug": "troubleshooting",
"sources": [
{
"path": "docs/OPERATIONS_RUNBOOK.md",
"sha256": "e466c8ffd55a0754167e29c64530943577ab8758645061248d671b26f2062d34",
"content": "# codewhale Operations Runbook\n\n> 阅读简体中文版:[zh_hans/OPERATIONS_RUNBOOK.md](zh_hans/OPERATIONS_RUNBOOK.md)。\n\nThis runbook covers practical debugging and incident response for the local CLI/TUI runtime.\n\n## Quick Triage\n\n1. Confirm binary + config:\n - `cargo run -- --version`\n - `cat ~/.codewhale/config.toml` (or inspect configured profile)\n2. Enable verbose logs:\n - `RUST_LOG=codewhale_tui=debug cargo run`\n - For HTTP retries/reconnects: `RUST_LOG=codewhale_tui::client=debug cargo run`\n3. Capture current state:\n - `ls ~/.codewhale/sessions`\n - `ls ~/.codewhale/sessions/checkpoints`\n - `ls ~/.codewhale/tasks`\n\n## Incident: Turn Hangs or Stream Stops\n\nSymptoms:\n- TUI remains in loading state\n- partial assistant output with no completion\n\nChecks:\n1. Inspect retry/health logs (`codewhale_tui::client`)\n2. Verify endpoint connectivity:\n - `curl -sS https://api.deepseek.com/beta/models -H \"Authorization: Bearer $DEEPSEEK_API_KEY\"`\n3. Confirm no local sandbox/permission deadlock in tool output\n\nActions:\n1. If a foreground shell command is running, press `Ctrl+B` to move it to the background (the turn keeps running and the command becomes a background job under `/jobs`); use `Ctrl+C` instead if you want to cancel the turn.\n2. If the command was started in the background, ask the assistant to use `Bash` with `action: \"cancel\"` and the returned process id.\n3. Use `Esc` or `Ctrl+C` to interrupt the current turn when you want to stop the request itself.\n4. Retry prompt; if still failing, restart TUI.\n5. On restart, verify the previous queued/in-flight runtime turn is shown as interrupted rather than left in a running state.\n\n## Incident: Network Outage / Offline Behavior\n\nExpected behavior:\n- New prompts are queued while offline mode is active\n- Queue state persists per session to\n `~/.codewhale/sessions/checkpoints/<session-id>.offline_queue.json`; a legacy\n global `offline_queue.json` is adopted once on upgrade\n\nChecks:\n1. Open queue in TUI: `/queue list`\n2. Confirm persisted queue file exists and updates timestamp\n\nActions:\n1. Restore connectivity\n2. Re-send queued entries (from `/queue edit <n>` + Enter, or normal input flow)\n3. Ensure queue file clears when queue is empty\n\n## Incident: Crash Recovery Needed\n\nExpected behavior:\n- Each session checkpoints to `~/.codewhale/sessions/checkpoints/<session-id>.json`;\n a legacy `latest.json` is still read for recovery but is no longer written\n- Startup begins a fresh session unless `--resume`/`--continue` is supplied\n\nActions:\n1. Resume prior work explicitly via `codewhale --resume <id>` (alias\n `codewhale resume <id>`; `codewhale --continue` recovers the newest\n interrupted checkpoint for the workspace) or `Ctrl+R` in TUI\n2. If checkpoint inspection is needed, inspect `checkpoints/<session-id>.json` (or a leftover legacy\n `latest.json`) for schema mismatch/details\n3. If schema is newer than binary supports, upgrade binary or remove stale checkpoint\n\n## Incident: Persistent State Schema Errors\n\nSymptoms:\n- Errors like `schema vX is newer than supported vY`\n\nAffected stores:\n- sessions (`~/.codewhale/sessions/*.json`)\n- runtime thread/turn/item records\n- tasks (`~/.codewhale/tasks/tasks/*.json`)\n\nActions:\n1. Confirm binary version and migration expectations\n2. Back up the state directory before editing\n3. Either:\n - run with a newer compatible binary, or\n - archive incompatible records and regenerate state\n\n## Incident: MCP/Tool Execution Failures\n\nChecks:\n1. Validate `~/.codewhale/mcp.json` schema and server command paths\n2. Confirm server process can start manually\n3. Check sandbox denials in TUI history / logs\n\nActions:\n1. Retry with required approvals (or YOLO only when appropriate)\n2. Temporarily disable failing MCP server and isolate issue\n3. Re-enable after verification with `/mcp` diagnostics\n\n## Post-Incident Checklist\n\n1. Preserve logs and relevant state files\n2. Record trigger, impact, and mitigation\n3. Add or update regression tests (retry/recovery/schema)\n4. Update this runbook and architecture docs if behavior changed\n"
},
{
"path": "docs/DOCKER.md",
"sha256": "3845d9e1bc72942ab1f6d714e6d6ed4bd204ccc2f40b29a87fa333893767ea79",
"content": "# Docker\n\n> 阅读简体中文版:[zh_hans/DOCKER.md](zh_hans/DOCKER.md)。\n\nCodewhale publishes a multi-arch Linux image to GitHub Container Registry\nfor each release.\n\nThe latest published image is 0.10.0 at `ghcr.io/hmbown/codewhale`.\nTo test the current `main` source, use [Building locally](#building-locally)\nin a checkout of [`codewhale-hq/Codewhale`](https://github.com/codewhale-hq/Codewhale).\n\n```bash\ndocker pull ghcr.io/hmbown/codewhale:latest\n```\n\n## Quick start\n\nRun the published image with a Docker-managed data volume:\n\n```bash\ndocker volume create codewhale-home\n\ndocker run --rm -it \\\n -e DEEPSEEK_API_KEY=\"$DEEPSEEK_API_KEY\" \\\n -v codewhale-home:/home/codewhale/.codewhale \\\n -v \"$PWD:/workspace\" \\\n -w /workspace \\\n ghcr.io/hmbown/codewhale:latest\n```\n\nUse a pinned release tag for reproducible installs:\n\n```bash\ndocker run --rm -it \\\n -e DEEPSEEK_API_KEY=\"$DEEPSEEK_API_KEY\" \\\n -v codewhale-home:/home/codewhale/.codewhale \\\n -v \"$PWD:/workspace\" \\\n -w /workspace \\\n ghcr.io/hmbown/codewhale:v0.10.0\n```\n\nThe pinned example uses the [0.10.0 release](https://github.com/codewhale-hq/Codewhale/releases/tag/v0.10.0).\n\n## Default image contract\n\n`ghcr.io/hmbown/codewhale:latest` and the semver tags are conservative runtime\nimages:\n\n- the container runs as the non-root `codewhale` user with UID/GID `1000:1000`\n- the image does not grant passwordless `sudo`\n- the image is meant to run Codewhale against mounted workspaces, not to mutate\n the base operating system at runtime\n- user state belongs in a volume mounted at `/home/codewhale/.codewhale`\n\nThat default is intentional. Keep using it for the smallest trust boundary. If a\nproject needs `apt-get`, compiler toolchains, Node/Python package managers,\ncustom CA certificates, or other host-like setup inside Docker, build an\nexplicit toolbox image instead of changing the default image contract.\n\n## Opt-in toolbox/custom image\n\nThe repository includes an example\n[`docs/examples/Dockerfile.toolbox`](examples/Dockerfile.toolbox) that extends\nthe official image with passwordless `sudo` and common development packages.\nBuild it with a pinned Codewhale tag when you want repeatable project\nenvironments:\n\n```bash\ndocker build -f docs/examples/Dockerfile.toolbox \\\n --build-arg CODEWHALE_IMAGE=ghcr.io/hmbown/codewhale:v0.10.0 \\\n --build-arg TOOLBOX_PACKAGES=\"git openssh-client curl build-essential pkg-config python3 python3-pip nodejs npm\" \\\n -t codewhale-toolbox:my-project .\n```\n\nUse `latest` only for throwaway testing. For shared projects, keep the\n`CODEWHALE_IMAGE` value pinned and review package additions like any other\ndevelopment-environment change.\n\nRun the toolbox image with the same workspace and state mounts:\n\n```bash\ndocker volume create codewhale-my-project-home\n\ndocker run --rm -it \\\n -e DEEPSEEK_API_KEY=\"$DEEPSEEK_API_KEY\" \\\n -v codewhale-my-project-home:/home/codewhale/.codewhale \\\n -v \"$PWD:/workspace\" \\\n -w /workspace \\\n codewhale-toolbox:my-project\n```\n\nInside this opt-in image, Codewhale can use commands such as\n`sudo apt-get update` and `sudo apt-get install -y <package>`. For repeatable\ncontainers, prefer baking those packages into the toolbox Dockerfile instead of\nletting a long-lived container drift.\n\nDo not bake API keys, SSH private keys, or other secrets into custom images.\nPass API keys at runtime and mount any SSH material deliberately, preferably\nread-only and only for projects that need it.\n\n### Compose toolbox template\n\nIf you prefer a repeatable `docker compose` entry point, use\n[`docs/examples/compose.toolbox.yml`](examples/compose.toolbox.yml). It builds\nthe toolbox image from [`docs/examples/Dockerfile.toolbox`](examples/Dockerfile.toolbox)\nand keeps the project state volume explicit:\n\n```bash\nCODEWHALE_IMAGE=ghcr.io/hmbown/codewhale:v0.10.0 \\\nCODEWHALE_TOOLBOX_IMAGE=codewhale-toolbox:my-project \\\nCODEWHALE_HOME_VOLUME=codewhale-my-project-home \\\nCODEWHALE_WORKSPACE=\"$PWD\" \\\ndocker compose -f docs/examples/compose.toolbox.yml run --rm codewhale\n```\n\nUse a different `CODEWHALE_TOOLBOX_IMAGE` and `CODEWHALE_HOME_VOLUME` for each\nproject that needs an independent toolchain or independent `.codewhale` state.\nThe Compose file also shows opt-in, read-only mounts for SSH material and local\nCA certificates; keep those commented out unless the project needs them.\n\n## Multiple independent projects\n\nUse one named state volume per project so sessions, config, skills, memory, and\nthe offline queue do not bleed across workspaces:\n\n```bash\nproject=\"$(basename \"$PWD\")\"\nimage=\"codewhale-toolbox:${project}\"\ndocker volume create \"codewhale-${project}-home\"\n\ndocker run --rm -it \\\n --name \"codewhale-${project}\" \\\n -e DEEPSEEK_API_KEY=\"$DEEPSEEK_API_KEY\" \\\n -v \"codewhale-${project}-home:/home/codewhale/.codewhale\" \\\n -v \"$PWDLine truncated
}
]
},
{
"id": "contribution",
"slug": "contribution",
"sources": [
{
"path": "CONTRIBUTING.md",
"sha256": "3d8a28e5ab0574aa5ba93dd7617c0f1e5c46a01806fc5ea4fdd56963e453e452",
"content": "# Contributing to codewhale\n\nThank you for your interest in contributing to codewhale! This document provides guidelines and instructions for contributing.\n\n## Getting Started\n\n### Prerequisites\n\n- Rust 1.89 or later (edition 2024)\n- Cargo package manager\n- Git\n\n### Setting Up Development Environment\n\n1. Fork and clone the repository:\n ```bash\n git clone https://github.com/YOUR_USERNAME/CodeWhale.git\n cd CodeWhale\n ```\n\n2. Build the current engine and terminal:\n ```bash\n CODEWHALE_BUILD_SHA=\"$(git rev-parse HEAD)\" cargo build --locked -p codewhale-cli\n ```\n\n3. Run the tests near your change (see [Fast local loop](#fast-local-loop)):\n ```bash\n scripts/dev-test.sh tui your_test_filter\n ```\n\n4. Run with development settings:\n ```bash\n ./target/debug/codewhale --version\n ./target/debug/codewhale\n ```\n\n### Testing the latest source\n\nThe canonical source is [`codewhale-hq/Codewhale`'s `main` branch](https://github.com/codewhale-hq/Codewhale/tree/main).\nRelease candidates land there after their CI gates pass, so contributors can\ntest and build on the same source. Tagged downloads remain the latest published\nrelease; their version can lag the development version on `main`.\n\nFor a fresh checkout of the current source:\n\n```bash\ngit clone --branch main https://github.com/codewhale-hq/Codewhale.git\ncd Codewhale\nCODEWHALE_BUILD_SHA=\"$(git rev-parse HEAD)\" cargo build --release --locked -p codewhale-cli\n./target/release/codewhale --version\n./target/release/codewhale\n```\n\nInclude the commit shown by `--version` when reporting a problem. If you work\nfrom a fork, add the canonical repository as `upstream` and fetch `upstream/main`\nbefore starting a change; preserve any local work when updating your branch.\n\n## Development Workflow\n\n### Code Style\n\n- Run `cargo fmt` before committing to ensure consistent formatting\n- Run `cargo clippy` and address all warnings\n- Follow Rust naming conventions (snake_case for functions/variables, CamelCase for types)\n- Add documentation comments for public APIs\n\n### Testing\n\n- Write tests for new functionality\n- Run the tests near your change (see [Fast local loop](#fast-local-loop));\n CI runs the whole suite on every pull request\n- Colocate unit tests beside the code they cover (standard Rust `#[cfg(test)]`\n modules), and add integration tests under the owning crate's `tests/`\n directory (for example `crates/tui/tests/` or `crates/state/tests/`). The\n repository root `tests/` directory is not used\n\n### Pre-push verification\n\nThese are the commands CI runs on every pull request. You do not need all\nof them before every push: run `cargo fmt`, then check and test the crates\nyou touched (see [Fast local loop](#fast-local-loop)). Run the full set\nlocally when a change spans many crates, or let CI run it for you:\n\n```bash\ncargo fmt --all -- --check\ncargo clippy --workspace --all-features --locked -- \\\n -D warnings \\\n -A clippy::uninlined_format_args \\\n -A clippy::too_many_arguments \\\n -A clippy::unnecessary_map_or \\\n -A clippy::collapsible_if \\\n -A clippy::assertions_on_constants\ncargo test --workspace --all-features --locked\n```\n\nThe release lane runs a stricter clippy that also lints test, bench, and\nexample targets. Use this form for release-bound work, because\n`--all-features` alone skips lints that will fail the release lane later:\n\n```bash\ncargo clippy --workspace --all-targets --all-features --locked -- \\\n -D warnings \\\n -A clippy::uninlined_format_args \\\n -A clippy::too_many_arguments \\\n -A clippy::unnecessary_map_or \\\n -A clippy::collapsible_if \\\n -A clippy::assertions_on_constants\n```\n\n#### Fast local loop\n\nThe full gate above is what CI enforces, but you do not need it for every\nedit. `crates/tui` is a ~750k-line crate, so the loop that stays fast is\nthe one that avoids rebuilding it more than necessary (numbers and the\nreasoning are in [`docs/BUILD_PERFORMANCE.md`](docs/BUILD_PERFORMANCE.md)):\n\n```bash\n# 1. Type-check first (seconds after the first build; no codegen, no link).\nscripts/dev-cargo.sh check -p codewhale-tui\n\n# 2. Run only the tests near your change (one crate, one filter).\nscripts/dev-test.sh tui fleet_setup\n# or: scripts/dev-test.sh crates/command-contract/src/elapsed.rs\n\n# 3. Run a whole crate's unit suite. scripts/dev-test.sh uses nextest when\n# it is installed (one process per test, all cores busy, slow tests\n# named; ~100 s here vs ~270 s with libtest).\ncargo install cargo-nextest --locked # once\nscripts/dev-test.sh tui\nscripts/dev-cargo.sh nextest run --workspace --all-features --locked\n\n# 4. The authoritative gate, exactly as CI runs it on your PR:\ncargo test --workspace --all-features --locked\n```\n\n`.config/nextest.toml` already serializes the PTY suite and bounds the\nintegration tests that spawn the real binary, so `cargo nextest run` is\nsLine truncated
},
{
"path": "docs/AGENT_ETHOS.md",
"sha256": "d9cd36fc7b6d9d236c68e62ffc92f41d3f3fab6e2e5eb9bf2bb2ae1d53f82331",
"content": "# Agent Ethos\n\n> 阅读简体中文版:[zh_hans/AGENT_ETHOS.md](zh_hans/AGENT_ETHOS.md)。\n\nCodewhale is maintained with agents, but it is not maintained by automation\nalone. Treat community reports and patches as real collaboration: people are\nbringing us machines, providers, regions, shells, packages, and edge cases we\ncould not cover by ourselves.\n\n## Stewardship\n\n- Verify live truth before acting. Check the current branch, release state,\n registry state, CI, and linked issues instead of trusting a handoff.\n- Issues are intake, not a privilege boundary. Do not auto-close good-faith\n issues because the reporter is not allowlisted. Ask for missing reproduction\n detail and leave room for maintainer triage.\n- PR gates exist for code review, CI load, and trust-boundary safety. They are\n not a quality judgment on the contributor. Keep dry-run mode unless a\n maintainer deliberately enables enforcement, and use warm copy when the gate\n comments.\n- Be generous with recurring contributors. When someone repeatedly brings\n useful reports or patches, use `/lgtmi` for issue access or `/lgtm` for PR\n access so the automation gets out of their way.\n- Preserve contributor credit. When harvesting work, inspect the PR and linked\n issues, keep author/co-author attribution where possible, add\n `Harvested from PR #N by @handle`, and credit the contributor in the\n changelog or release notes.\n- Make credit machine-readable. If a harvested commit cannot preserve the\n contributor as the author, add a `Co-authored-by` trailer with the GitHub\n numeric noreply address from `.github/AUTHOR_MAP` or\n `gh api users/<login> --jq '\"\\(.id)+\\(.login)@users.noreply.github.com\"'`.\n Do not use `.local`, placeholder, bot/tool, or raw third-party emails for\n human contributor credit.\n- Deferral is a maintainer action, not a dismissal. If a PR or issue is not\n ready, say what is blocked, what evidence would change the decision, and\n which part of the work remains valuable.\n\n## Agent Workflow\n\n- Use sub-agents for exploration, review, and verification, but keep a human\n maintainer posture in the parent session. Sub-agent output is evidence; the\n parent is responsible for the final decision.\n- Personally review community PRs before merging, harvesting, closing, or\n deferring them. Do not close work based only on title, labels, or an agent's\n summary.\n- Prefer narrow, reversible changes that match the existing codebase. Avoid\n drive-by refactors while harvesting community work.\n- Run the smallest meaningful validation first, then broaden tests when a\n change touches shared behavior, release plumbing, auth, sandboxing,\n providers, or UI workflows.\n- Do not tag, publish, push release artifacts, or create GitHub releases\n without explicit maintainer approval.\n\n## Product Tone\n\nCodewhale should feel like a capable coding harness with a public community,\nnot a closed queue. Automation should reduce maintainer load while making\ncontributors feel seen, credited, and able to keep helping.\n"
},
{
"path": "docs/CONTRIBUTORS.md",
"sha256": "81cc78f58b7f9fb88607261ffb446faf9b807c55590ea41028b561a65683a078",
"content": "# Contributors\n\nCodewhale is built in the open with a growing community of contributors. Every\nissue report and pull request is real project work — welcome at any experience\nlevel. This is the full per-PR contributor record, grouped into release/time\nbands with the newest band first so it stays scannable. Expand any band to see\neveryone.\n\nFor the live list, see the\n[GitHub contributors page](https://github.com/codewhale-hq/CodeWhale/graphs/contributors),\n[`AUTHOR_MAP`](https://github.com/codewhale-hq/CodeWhale/blob/main/.github/AUTHOR_MAP),\nand [CHANGELOG.md](../CHANGELOG.md).\n\n## Organizational thanks\n\n- **[DeepSeek](https://github.com/deepseek-ai)** — the models and support that got this project started. 感谢 DeepSeek 提供模型与支持。\n- **[DataWhale](https://github.com/datawhalechina)** 🐋 — for the support and for welcoming us into the Whale Brother family. 感谢 DataWhale 的支持。\n- **[OpenWarp](https://github.com/zerx-lab/warp)** — for prioritizing Codewhale support and collaborating on a better terminal-agent experience.\n- **[Open Design](https://github.com/nexu-io/open-design)** — for support and collaboration around design-forward agent workflows.\n\nThe maintainer rule: reports and PRs are real project work, even when the final\npatch has to be narrowed, delayed, or harvested into a maintainer branch.\nAdapted contributions keep visible credit in commits and PR bodies, the\nchangelog or release notes, and this contributor record.\n\n---\n\n## Contributors by time\n\n<details open>\n<summary><strong>Unreleased</strong></summary>\n\n**Merged or adapted contributions**\n\n</details>\n\n<details open>\n<summary><strong>v0.10.2 — terminal, recovery and reliability</strong></summary>\n\n**Contributions**\n\n- **[Sh1Zuku / SparkofSpike](https://github.com/SparkofSpike)** — live network-policy updates and goal milestone hand-back ([#6928](https://github.com/codewhale-hq/Codewhale/pull/6928), [#6930](https://github.com/codewhale-hq/Codewhale/pull/6930)), and a Codewhale home reached through a symlink or junction ([#6947](https://github.com/codewhale-hq/Codewhale/issues/6947)).\n- **[dajiaohuang](https://github.com/dajiaohuang)** — cache-write token accounting, with missing and explicit-zero usage preserved ([#6913](https://github.com/codewhale-hq/Codewhale/pull/6913)).\n- **[gaord](https://github.com/gaord)** — embedder-declared telemetry surface support without changing collection policy ([#6916](https://github.com/codewhale-hq/Codewhale/pull/6916)).\n- **[Lstarsky0](https://github.com/Lstarsky0)** — localized `/profile` replies across all 15 complete locale packs ([#6919](https://github.com/codewhale-hq/Codewhale/pull/6919)), and workflow gates that block their own role rejected at plan admission ([#6952](https://github.com/codewhale-hq/Codewhale/pull/6952)).\n- **[LIghtJUNction](https://github.com/LIghtJUNction)** — plugin shell install and in-TUI plugin OAuth sign-in with `/connect` and `/disconnect` ([#6950](https://github.com/codewhale-hq/Codewhale/pull/6950)).\n- **[jayanthvee](https://github.com/jayanthvee)** — Windows npm launcher guidance and targeted process shutdown ([#6906](https://github.com/codewhale-hq/Codewhale/pull/6906)).\n- **[asto18089](https://github.com/asto18089)** — reference fix for longer browser sign-in callback windows ([#6865](https://github.com/codewhale-hq/Codewhale/issues/6865)).\n\n**Reports and verification**\n\n- **[BX166](https://github.com/BX166)** — reported three provider failure modes measured on AICraft's own traffic: a cold model that reads as a dead connection, a listed model that fails on every call, and a response cut at the output ceiling that reports `stop` ([#6889](https://github.com/codewhale-hq/Codewhale/issues/6889)).\n\n</details>\n\n<details>\n<summary><strong>v0.10.1 — reliability and first-run fixes</strong></summary>\n\n**Merged or adapted contributions**\n\n- **[gaord](https://github.com/gaord)** — exposed call-specific workspace changes to Runtime clients ([#6817](https://github.com/codewhale-hq/Codewhale/pull/6817)) and canonical skill-detail/review routes ([#6869](https://github.com/codewhale-hq/Codewhale/pull/6869)).\n- **[asto18089](https://github.com/asto18089)** — fixed preferred search-language selection ([#6860](https://github.com/codewhale-hq/Codewhale/pull/6860)), image metadata for model input ([#6858](https://github.com/codewhale-hq/Codewhale/pull/6858)), automation deletion wording and retained-run cleanup ([#6864](https://github.com/codewhale-hq/Codewhale/pull/6864)), and compaction-anchor regression coverage ([#6857](https://github.com/codewhale-hq/Codewhale/pull/6857)).\n- **[aboimpinto](https://github.com/aboimpinto)** — extracted portable config/status/permission command contracts while preserving host-owned mutation and queue-worker readiness ([#6832](https://github.com/codewhale-hq/Codewhale/pull/6832)).\n- **[hodeswildsmith455-boop](httpsLine truncated
},
{
"path": "docs/RELEASE_CHECKLIST.md",
"sha256": "b131f758e280d3f037b408ddaddd79db723ed1a6bba7c6296e7480138e1b379e",
"content": "# Release Checklist\n\nFollow this sequence from the canonical `/Volumes/VIXinSSD/CW/codewhale`\ncheckout on `main`. Agent-owned preparation lands as verified slices on `main`;\nit requires no release branch, worktree, nested clone or preparation PR.\nContributor PRs still land as PRs. Treat any unchecked required gate as a release\nblocker.\n\nFor deeper context on the underlying tools (preflight scripts, npm smoke,\npublish-crates), see [`RELEASE_RUNBOOK.md`](RELEASE_RUNBOOK.md).\nFor larger milestone releases, add any version-specific acceptance matrix to\nthe existing release packet before tagging; use it for provider routes, feature\ngates, GUI/runtime smoke, remote-workbench decisions, and credit hygiene that the\ngeneric checklist does not enumerate. Record its candidate SHA, owners, local\ncheck results, hosted run URLs, artifact inventory, install/provider receipts,\nknown limitations and publication approval. These proofs are separate.\n\n## 0. Reconcile the canonical checkout\n\n- [ ] Inspect the branch, status, upstream and alternate checkouts before editing:\n ```bash\n git branch --show-current\n git status --short --branch\n git log -5 --oneline\n git worktree list\n git fetch origin main\n git log --left-right --oneline main...origin/main\n ```\n- [ ] The canonical checkout is on `main`. Recover stranded work only after\n preserving dirty/untracked files and comparing commits with current\n `origin/main`. Keep a recoverable backup and unresolved inventory; do not\n reset away work, stash it indefinitely or create another development lane.\n- [ ] Partition files among active writers. Check status before staging and\n stage only owned paths. Historical branches/checkouts are inventoried;\n deleting them requires explicit Hunter approval even if a helper calls\n their tips safe to delete.\n\n## 1. CHANGELOG entry exists for the version\n\n- [ ] `CHANGELOG.md` has a `## [X.Y.Z] - YYYY-MM-DD` heading at the top\n- [ ] The entry credits every external contributor, harvested PR author,\n linked issue reporter, reproduction/log provider, reviewer, and\n verification helper whose work materially shaped this version. Get the\n commit list with:\n ```\n git log vPREV..HEAD --no-merges --format=\"%h %an <%ae> %s\" \\\n | grep -v '<your-email@…>'\n ```\n For each contributor, link both their display name and (when known)\n `@github-handle`. Then inspect linked issues and harvested PRs so\n reporters/helpers are not lost just because they did not author commits.\n Keep `docs/CONTRIBUTORS.md` and `web/lib/release-credits.ts` consistent.\n- [ ] The entry uses the Keep a Changelog headers — `Added`, `Changed`,\n `Fixed`, `Security`, `Removed`, `Deprecated`. Add `Known issues` only\n if there is something material the user must work around.\n- [ ] The entry mentions all referenced issue/PR numbers as `#NNNN` so the\n auto-linker on GitHub picks them up.\n- [ ] Run `scripts/sync-changelog.sh` to regenerate `crates/tui/CHANGELOG.md`\n (the recent-releases slice embedded in the binary for `/change`). Do\n not edit that file by hand, and do not copy the full root changelog\n into it — older entries live in `docs/CHANGELOG_ARCHIVE.md`.\n- [ ] Run `scripts/release/check-feature-release-notes.sh vPREV HEAD`. Every\n issue-linked `feat` commit must leave a receipt in `CHANGELOG.md` or the\n archive; the Version drift CI gate runs the same check with full history.\n\n## 2. Version pins are in sync\n\n- [ ] Use `./scripts/release/prepare-release.sh X.Y.Z` when version pins or\n generated sources need preparation. Reuse a valid preparation receipt\n when those sources are already current. The helper bumps the\n workspace version, every per-crate dependency pin, the npm wrapper\n (`version` + `codewhaleBinaryVersion`), Runtime SDK, VS Code extension\n and lock, remote-smoke default, public source-candidate facts, and README\n install-tag examples; it refreshes the Cargo/npm locks, regenerates\n `crates/tui/CHANGELOG.md` and `web/lib/facts.generated.ts`, and ends\n by running the version and OHOS gates. Write the CHANGELOG entry\n **before** running it. The helper is safe to rerun at the requested\n workspace version; it skips replacements but refreshes both generated\n files and reruns the gates.\n- [ ] `npm/deepseek-tui/package.json` remains private/compatibility-only and\n is **not** bumped or published.\n- [ ] `./scripts/release/check-versions.sh` reports\n `Version state OK: workspace=X.Y.Z, npm=X.Y.Z, npm-binary=X.Y.Z, lockfile in sync.`\n- [ ] `./scripts/release/check-ohos-deps.sh` reports that the OpenHarmony\n Windows linker keeps the target/sysroot flags, the target enables the\n `rquickjs-sys` bindgen edge, and its graph does not pull the unsupporLine truncated
}
]
},
{
"id": "vocabulary",
"slug": "vocabulary",
"sources": [
{
"path": "docs/FLEET.md",
"sha256": "134c6a358522c6367a8f004813daab56150a371e9433811236524fb2978ea0cf",
"content": "# Agent fleet\n\n> Baca terjemahan bahasa Indonesia: [id/FLEET.md](id/FLEET.md)\n\nAgent fleet is the local-first roster and member-selection layer for durable\nmulti-worker runs. It does not execute or authorize work. After fleet resolves\nwho should participate, the delegated coordinator launches a headless\n`codewhale exec` run and the Runtime tracks it durably. See\n[AGENT_RUNTIME.md](AGENT_RUNTIME.md) for how sub-agents, `exec`, and\nfleet-backed workers converge on one runtime. In product language, a user may\nstill \"open a sub-agent\"; in architecture language, durable nested work uses a\nfleet member identity with delegated runtime execution.\n\n## Naming and compatibility boundary\n\n**Fleet** is the public product noun. The durable ledger, saved rosters, config\ntables, and `--fleet` flag share that name:\n\n| Surface | Canonical |\n| --- | --- |\n| CLI | `codewhale fleet …` |\n| Slash command | `/fleet …` |\n\nThese shared names are load-bearing wherever changing them would break\nexisting workspaces, receipts, or scripts:\n\n- the durable ledger `.codewhale/fleet.jsonl` and the log directories\n `.codewhale/fleet/` and `.codewhale/fleet-host/`;\n- saved rosters `fleets/<name>.toml` and their `schema = \"fleet\"` header, under\n `$CODEWHALE_HOME/` or the workspace's `.codewhale/` (checked-in rosters at the\n workspace root's `fleets/` are still read);\n- the `[fleet]` config table (inline `[fleets.*]` tables were removed in 0.9.14; named fleets live in `fleets/<name>.toml` files);\n- the `codewhale workflow run --fleet <name>` flag;\n- wire, receipt, and control-plane operation ids such as `fleet.status`.\n\nThe rest of this document uses fleet as the public product noun and retains\nthese literal paths, keys, flags, and ids.\n\nUse a fleet roster rather than anonymous short-lived `agent` fanout whenever a\ndelegated run needs stable member identities across retries, sleep/restart,\nremote execution, receipts, or a ledgered audit trail. The initial CLI surface\nis:\n\nFor a guided start-to-monitor walkthrough that combines fleet task specs with\nWorkflow authoring, see [fleet + Workflow Tutorial](FLEET_WORKFLOW_TUTORIAL.md).\n\n```sh\ncodewhale fleet init\ncodewhale fleet run tasks.json --check # validate only; nothing is created or launched\ncodewhale fleet run tasks.json --max-workers 4\ncodewhale fleet status\ncodewhale fleet inspect <worker-id>\ncodewhale fleet logs <worker-id>\ncodewhale fleet artifacts <worker-id>\ncodewhale fleet interrupt <worker-id>\ncodewhale fleet restart <worker-id>\ncodewhale fleet resume <run-id>\ncodewhale fleet stop --all\n```\n\n`codewhale fleet resume <run-id>` is the restart-recovery verb: it replays the\nledger, reconciles any in-flight lease whose worker stopped heartbeating\n(retrying within the task's budget, else failing and escalating per the alert\npolicy), and prints the post-resume status. It launches no new work and is\nidempotent, so it is safe to run after a manager exit, laptop sleep, or runtime\nrestart.\n\nCoordinator state for fleet-backed runs is stored under the workspace in\n`.codewhale/fleet.jsonl`. Worker logs and adapter logs are stored under\n`.codewhale/fleet/` and `.codewhale/fleet-host/`.\n\n## Public contract: identity, membership, and selection\n\n**Fleet** = the user's model inventory: who is in the roster and which member is selected.\n\nA public fleet identity consists only of:\n\n- a stable member id and an optional user-facing name;\n- a semantic role, such as `explore`, `implement`, or `reviewer` (the legacy\n spellings `worker`, `scout`, `builder`, `verifier`, `consultant`, and `oracle`\n are still accepted on input and map to `general`, `explore`, `implement`,\n `test`, and `advisor`);\n- an exact provider/model identity, or an explicit inherited route;\n- visible roster state or origin.\n\nProject or workspace trust, filesystem and network reach, secret access,\napproval mode, sandboxing, tool authorization, and every other form of runtime\nauthority are separate delegated-coordination and Runtime policy inputs. They\nare never fleet identity fields, and they never select or reroute a fleet\nmember. The Runtime applies and clamps those policies only after member\nselection; if the selected member cannot run inside the effective envelope,\nlaunch fails closed instead of choosing somebody else.\n\nNatural-language member selection is deterministic. A caller may name:\n\n- an exact member id, optionally as `member:<id>` or `id:<id>`;\n- a unique user-facing member name, optionally as `name:<name>`;\n- a unique semantic role, for example `explore` or `role:explore`;\n- an exact pinned model id, for example `deepseek-v4-flash`, or its offline\n display name, for example `DeepSeek V4 Flash`; or\n- an exact `route:<provider>/<model>`.\n\nAn unqualified exact member id wins. Every other match succeeds only when it\nidentifies one distinct roster member. Multiple matches produce an ambiguity\nerror Line truncated
},
{
"path": "docs/MODES.md",
"sha256": "7026b81d483cfaf911f6467f2ef318c7eb51dd84bc8c0aaf0788f3e53138269d",
"content": "# Modes and Permission Postures\n\n> 阅读简体中文版:[zh_hans/MODES.md](zh_hans/MODES.md)\n\nCodewhale has three related concepts:\n\n- **TUI mode**: what kind of visible interaction you're in (Plan/Work/Operate).\n- **Permission posture**: how aggressively the UI asks before executing tools.\n- **Workflow**: named steps that coordinate sub-agents, with dependencies and\n results, available in any TUI mode.\n\nModel selection is separate. `--model auto` and `/model auto` route each turn to\na concrete model and thinking level; they are not TUI modes and are not part of\nthe `Tab` cycle.\n\nWorkflow runs named steps through the same sub-agent runtime; Fleet manages\ntheir saved roles and model assignments. A workflow adds ordering, result\nhandoffs, gates and a progress view. The active mode and permission posture\nstill control what each step may execute.\n\nBefore assigning steps, query `agent(action=\"roster\")` for the saved Fleet\nmodels and roles. A plan child can select a listed model with `model`, or use\nthe saved `role`/`profile` assignment. An Exact Fleet fixes each member's route.\n\n## TUI Modes\n\nPress `Tab` to complete composer menus or cycle through the visible modes\nwhen the composer is empty: **Plan → Work → Operate → Plan**. `Tab` never sends\nor queues composer text; use `Enter` to send or queue it.\nPress `Shift+Tab` to cycle permission posture (Ask → Auto-Review → Full Access).\nEvery change of effective permission writes a `Permissions changed to …` line\nin the transcript.\nPress `Ctrl+T` to cycle reasoning effort.\nRun `/mode` to open the mode picker, or switch directly with `/mode work`,\n`/mode plan`, or `/mode operate`.\n\n- **Plan**: design-first prompting. The stable primitive names remain familiar, but the runtime centrally refuses file mutation and shell execution. Read-only inspection and policy-allowed research, including deferred Web search/fetch, remain available. When a Plan turn successfully finishes a nonempty response, including a prose-only plan, the TUI asks how to continue: Work (Ask), Work (Auto-Review), or keep planning. Work sends the exact approved response as a normal follow-up and preserves that turn's existing To-dos, or adds one pending plan item without replacing unrelated work.\n- **Work** (internally `agent`): ordinary multi-step execution. The first-turn toolbox includes `read`, `write`, `edit`, `bash`, `agent`, `workflow`, and `todo_write`, plus `create_goal`, `get_goal`, and `update_goal` so goal controls are available without discovery. The agent calls `create_goal` when a request is a durable objective; the host never infers a goal from wording, and the contract must not tell the model otherwise. Approval, sandbox, repository law, and managed policy decide what may execute.\n- **Operate**: Work at full strength, the \"ultra\" mode. Same tools and authority as Work; the difference is how they are used. Each substantive request becomes a goal (`create_goal`), the plan stays visible (`todo_write`), multi-part work runs through `workflow` and parallel `agent` workers, non-trivial changes get an independent reviewer before they are called done, long commands keep running in the background, and recurring or watch-type work is offered as an `automation` (created after approval). It keeps going until the goal is verified, blocked on you, or paused.\n\n`Act` and `/mode act` remain compatibility aliases for Work. Saved settings\nstill normalize to the internal value `agent`.\n\n### Tool availability by mode\n\n| Tool family | Plan | Work | Operate |\n|:---|:---:|:---:|:---:|\n| `read` and policy-allowed deferred research tools | yes | yes | yes |\n| `write` and `edit` | visible names; execution denied | approval- and policy-gated | same as Work |\n| `bash` | visible name; execution denied | approval- and policy-gated | same as Work; delegation is preferred when parallelism or isolation helps |\n| `agent` | yes, subject to child-depth authority | yes, subject to child-depth authority | yes, subject to child-depth authority |\n| Deferred native, MCP, and plugin tools | discoverable through `tool_search` when policy permits | same | same |\n| Paid or external-service tools | follows permission posture | follows permission posture | follows permission posture |\n| Access outside the workspace root | explicit trusted paths only | only through trusted paths or trust mode | same trusted-path/trust policy as Work; fleet profiles never widen it |\n\nOperate changes scheduling emphasis, not authority. It neither adds a\nmode-specific tool denial nor bypasses the active approval, sandbox, shell,\nask-rule, repository-law, or managed-policy boundary. Plan remains the\nmode-specific execution boundary for shell and write-capable tools; that\nauthority difference does not require a different primitive vocabulary.\n\n### Operate loop (one screen)\n\n```text\nUser message\n → small / chat / one-file? → parent does it (Work-equLine truncated
},
{
"path": "docs/public-surface-facts.json",
"sha256": "1d688a9b6a08de2bbf5e1122594aa1e0b47cb30cc7d94e27b8d4df7a7ba86a26",
"content": "{\n \"schemaVersion\": 2,\n \"product\": {\n \"name\": \"Codewhale\",\n \"description\": \"Terminal coding agent for supported hosted and local models. One runtime on your machine. Rust, MIT.\",\n \"positioning\": \"Terminal-native, model/provider-neutral, local-first coding agent\",\n \"license\": \"MIT\",\n \"terminology\": {\n \"Fleet\": \"the user's model inventory: who is in the roster and which member is selected\",\n \"Workflow\": \"what order the work follows\",\n \"Lane\": \"one running Workflow instance\",\n \"Runtime\": \"where, how, and with what authority selected work executes\"\n },\n \"sources\": [\n \"Cargo.toml\",\n \"LICENSE\",\n \"README.md\",\n \"npm/codewhale/package.json\",\n \"docs/FLEET.md\"\n ]\n },\n \"sourceCandidate\": {\n \"version\": \"0.10.2\",\n \"providerCount\": 50,\n \"toolCount\": 79,\n \"sandboxBackends\": [\n \"seatbelt (macOS, when available)\",\n \"bubblewrap (Linux, default when installed and working)\"\n ],\n \"sources\": [\n \"Cargo.toml\",\n \"crates/tui/src/config.rs\",\n \"crates/tui/src/sandbox/mod.rs\",\n \"web/scripts/derive-facts.mjs\"\n ],\n \"providerCountDefinition\": \"Website descriptor identities in this source snapshot, excluding Custom and retired identities; includes protocol/plan variants. Not a count of distinct vendors, ProviderKind identities, live catalogs, or providers in any published release.\"\n },\n \"latestPublishedRelease\": {\n \"tag\": \"v0.10.1\",\n \"version\": \"0.10.1\",\n \"publishedAt\": \"2026-10-08T01:47:44Z\",\n \"url\": \"https://github.com/codewhale-hq/CodeWhale/releases/tag/v0.10.1\",\n \"sources\": [\n \"web/data/latest-published-release.json\"\n ]\n },\n \"install\": {\n \"recommended\": \"curl -fsSL https://codewhale.net/install.sh | sh\",\n \"binaries\": [\n \"codewhale\",\n \"codew\"\n ],\n \"channels\": {\n \"npm\": \"published releases only\",\n \"cargo\": \"published crates only\",\n \"prebuiltArchives\": \"published GitHub Releases only\",\n \"cnbMirror\": \"documented targets only\"\n },\n \"androidTermux\": {\n \"status\": \"preview\",\n \"npm\": \"preview\",\n \"requiresMatchingPublishedAssets\": true,\n \"sourceBuild\": true\n },\n \"sources\": [\n \"README.md\",\n \"npm/codewhale/package.json\",\n \"npm/codewhale/README.md\",\n \"npm/codewhale/scripts/artifacts.js\",\n \"docs/INSTALL.md\",\n \"docs/CNB_MIRROR.md\"\n ]\n },\n \"control\": {\n \"modes\": [\n \"Plan\",\n \"Work\",\n \"Operate\"\n ],\n \"permissionPostures\": [\n \"Ask\",\n \"Auto-Review\",\n \"Full Access\"\n ],\n \"shortcuts\": {\n \"mode\": {\n \"chord\": \"Tab\",\n \"when\": \"composer empty\"\n },\n \"permissionPosture\": {\n \"chord\": \"Shift+Tab\",\n \"when\": \"always (suppressed only under a non-Config modal)\"\n }\n },\n \"sources\": [\n \"docs/MODES.md\",\n \"docs/KEYBINDINGS.md\",\n \"crates/tui/src/settings.rs\"\n ]\n },\n \"toolSurface\": {\n \"defaultActive\": [\n \"read\",\n \"write\",\n \"edit\",\n \"file_search\",\n \"bash\",\n \"agent\",\n \"workflow\",\n \"todo_write\",\n \"create_goal\",\n \"get_goal\",\n \"update_goal\",\n \"load_skill\"\n ],\n \"schemas\": {\n \"read\": [\n \"path\",\n \"offset?\",\n \"limit?\"\n ],\n \"write\": [\n \"path\",\n \"content\"\n ],\n \"edit\": [\n \"path\",\n \"edits\"\n ],\n \"bash\": [\n \"command\",\n \"timeout?\"\n ]\n },\n \"deferred\": {\n \"Web\": [\n \"search\",\n \"fetch\",\n \"wait\"\n ]\n },\n \"compatibility\": {\n \"legacyAliases\": \"hidden-exact\",\n \"modelVisible\": false,\n \"toolSearchDiscoverable\": false\n },\n \"activationCache\": {\n \"maximumNames\": 8,\n \"maximumSchemaBytes\": 16384,\n \"scope\": \"per conversation; each subagent owns an independent policy-filtered cache\"\n },\n \"agentConcurrency\": {\n \"defaultConfigured\": 64,\n \"maximumConfigured\": 128,\n \"maximumAdmitted\": 1024\n },\n \"sources\": [\n \"docs/TOOL_SURFACE.md\",\n \"docs/RUNTIME_SIMPLIFICATION_DESIGN.md\",\n \"crates/tui/src/core/engine/tool_catalog.rs\",\n \"crates/tui/src/tools/registry.rs\",\n \"crates/tui/src/config/subagent_limits.rs\"\n ]\n },\n \"surfaces\": {\n \"availableInSourceCandidate\": [\n \"TUI\",\n \"codewhale exec\",\n \"Web client\",\n \"Runtime API\",\n \"MCP\",\n \"Fleet\"\n ],\n \"sources\": [\n \"docs/GUIDE.md\",\n \"docs/WELine truncated
}
]
},
{
"id": "constitution",
"slug": "constitution",
"sources": [
{
"path": "docs/ARCHITECTURE.md",
"sha256": "48c0f8b2a91a394763d9a0111a98d3c63bceab1435150ddb9ae1c6bc9873db40",
"content": "# Codewhale Architecture\n\n> 阅读简体中文版:[zh_hans/ARCHITECTURE.md](zh_hans/ARCHITECTURE.md)。\n\nCodewhale Engine is the existing Rust execution runtime. The\n[Runtime API](RUNTIME_API.md) is its client interface, and\n[TypeScript mods](EXTENSIONS.md) contribute reviewed extensions.\n\nCurrent boundary note (read the workspace version from `Cargo.toml`; this\nboundary has held since v0.9.1):\n- `crates/tui` is still the live end-user runtime for the TUI, runtime API, task manager, and tool execution loop.\n- Other workspace crates are being split out incrementally, but they are not yet the sole runtime source of truth.\n\n<img src=\"assets/architecture.webp\" alt=\"Codewhale architecture: clients reach the one turn loop, Engine::run_turn, through the CLI or the Runtime API; the engine uses crates/core to build requests, runs tools under approval and sandbox policy, routes to any provider through crates/config, and logs everything model-visible to the session store.\" width=\"1000\">\n\nThe diagram draws the Runtime API and the task manager as their own boxes; today\nboth are hosted inside `crates/tui`, as the note above says. The GPUI desktop\napp and the VS Code extension live outside this repository. The arrow from the\nengine to the session log follows the \"model-visible means logged\" contract\nrather than a traced write path.\n- `crates/tui` is being split into crates sized as agent work partitions:\n contracts, utilities, services, providers, runtime, leaf feature crates,\n TUI views and hosts, in the order `docs/design/TUI_DECONSTRUCTION.md`\n records. The TUI stays the only crate that writes to the terminal. Until a\n module has moved, its path under `crates/tui/src` is still where it lives.\n- The LSP subsystem (`crates/tui/src/lsp/`) is fully wired into the engine's\n post-tool-execution path (`core/engine/lsp_hooks.rs`), providing inline\n diagnostics after `File` write, edit, and patch actions.\n- The swarm agent system was removed in v0.8.5. The active sub-agent surface is\n the single `agent` tool; persistent RLM sessions are available through the\n deferred `rlm` action family.\n No model-visible swarm tool remains in the active codebase.\n\n## High-Level Overview\n\n```\n┌─────────────────────────────────────────────────────────────────┐\n│ User Interface │\n│ ┌─────────────────┐ ┌─────────────────┐ ┌────────────────┐ │\n│ │ TUI (ratatui) │ │ One-shot Mode │ │ Config/CLI │ │\n│ └────────┬────────┘ └────────┬────────┘ └────────┬───────┘ │\n└───────────┼─────────────────────┼────────────────────┼──────────┘\n │ │ │\n ▼ ▼ ▼\n┌─────────────────────────────────────────────────────────────────┐\n│ Core Engine │\n│ ┌─────────────────────────────────────────────────────────┐ │\n│ │ Agent Loop (core/engine.rs) │ │\n│ │ ┌─────────┐ ┌─────────────┐ ┌──────────────────────┐ │ │\n│ │ │ Session │ │ Turn Mgmt │ │ Tool Orchestration │ │ │\n│ │ └─────────┘ └─────────────┘ └──────────────────────┘ │ │\n│ └─────────────────────────────────────────────────────────┘ │\n└─────────────────────────────────────────────────────────────────┘\n │ │ │\n ▼ ▼ ▼\n┌──────────────────────────────────────────────────────Line truncated
}
]
},
{
"id": "tools",
"slug": "tools",
"sources": [
{
"path": "docs/TOOL_SURFACE.md",
"sha256": "ecfb9e76e13225dabd3313b89c40c8bc904beb8be1d88e370151df72a90bc61a",
"content": "# Tool surface\n\n> 阅读简体中文版:[zh_hans/TOOL_SURFACE.md](zh_hans/TOOL_SURFACE.md)。\n\nThis document describes the current model-facing tool contract. The v0.9.1\ncutover that produced it is recorded in `docs/RUNTIME_SIMPLIFICATION_DESIGN.md`;\nread the workspace version from `Cargo.toml`, not from this line. The registry\nremains larger than the first-turn catalog so\nsaved transcripts can replay and uncommon capabilities can be loaded on demand.\nThe model should learn one canonical name for each common operation.\n\nImplementation sources:\n\n- `crates/tui/src/core/engine/tool_catalog.rs` owns the eager/deferred catalog.\n- `crates/tui/src/tools/registry.rs` registers canonical tools and hidden aliases.\n- `crates/tui/src/tools/{file,file_tool,shell}.rs` own the small foreground\n primitive behavior and schemas; the other native tools remain searchable.\n- `docs/RUNTIME_SIMPLIFICATION_DESIGN.md` records the v0.9.1 cutover and receipt.\n\n## Default-active contract\n\nNew turns start with twelve eager native names plus synthetic `tool_search`:\n\n1. `read`\n2. `write`\n3. `edit`\n4. `file_search`\n5. `bash`\n6. `agent`\n7. `workflow`\n8. `todo_write`\n9. `create_goal`\n10. `get_goal`\n11. `update_goal`\n12. `load_skill`\n13. `tool_search` (synthetic, always active)\n\nThe twelve native names are `DEFAULT_ACTIVE_NATIVE_TOOLS` in\n`crates/tui/src/core/engine/tool_catalog.rs`, pinned by\n`default_active_contract_keeps_discovery_and_core_tools_eager`. An authority\nboundary may remove `agent` at the maximum child depth, but route size alone\nmust not change this core vocabulary.\n\nThe direct schemas deliberately stay small:\n\n| Tool | Input | Purpose |\n|---|---|---|\n| `read` | `path`, optional `offset`, optional `limit` | Read a bounded file window with explicit continuation or truncation notices. |\n| `write` | `path`, `content` | Create or replace a file. |\n| `edit` | `path`, `edits` | Apply one or more unambiguous text replacements against one original snapshot. |\n| `bash` | `command`, optional `timeout`, optional `description` | Run one cancellable foreground shell command and return a bounded tail. The optional description is display-only. |\n| `agent` | delegated task and optional scope/context controls | Start or inspect focused child work. |\n| `workflow` | plan/script/source_path plus run controls | Coordinate multi-agent phases with dependencies and completion checks. |\n| `todo_write` | complete replacement list of `{content, status}` items | Keep optional, agent-owned progress notes for genuinely multi-step work. |\n| `create_goal` | objective plus optional budget | Start the session goal the turn works toward. |\n| `get_goal` | none | Read the active goal and its progress. |\n| `update_goal` | terminal status | Mark the goal complete or blocked. |\n| `tool_search` | `query`, optional matching controls | Discover policy-allowed deferred tools and add selected schemas to this conversation's toolbox. |\n\nMode is an authority decision, not a synonym system. Plan, Work, and Operate\nuse the same primitive identities. Plan centrally refuses `write`, `edit`, and\n`bash`; Work and Operate still pass those calls through approval, sandbox,\ntrusted-path, repository-law, and managed-policy gates. Full Access changes\nordinary approval behavior but does not bypass hard safety or repository law.\n\n`update_plan` remains registered only for saved-artifact compatibility and is\nnot model-visible. `tasks`, `Git`, `Run`, `Web`, `remember`, and other\nspecialized capabilities are searchable rather than first-turn ceremony.\n\nA Bash description appears as a muted, bounded note under the command on the\nTUI shell card, including on automatic runs. It never replaces the command and\nis excluded from execution, exact approval keys and Auto-Review input. The\noriginal description remains in the recorded tool input and exports. Approval\nprompts, `/jobs`, the activity inspector, ACP and other Runtime clients keep\nshowing the command; this change adds no description row to those surfaces.\n\n## Local code execution\n\n`code_execution` (Python) and `js_execution` (Node.js) use the same\npermission-aware local launcher as workspace task gates and test runs. Ordinary\napproval retains the effective session policy. To retry a denied exact call\nwith wider permissions, supply `sandbox_permissions` (`workspace-write` or\n`danger-full-access`) and a nonempty `justification`; Ask mode requires explicit\none-shot user approval. The approved policy affects only that call.\n\nBoth tools read source from stdin, return stdout/stderr/return_code, and keep\nthe existing timeout and process-tree cleanup. They are not persistent REPLs;\ntracebacks refer to stdin rather than a temporary script path. The separate\nRLM/REPL kernel is not changed by this launcher integration.\n\nPlatform/backend limits of the shared launcher still apply: no available local\nwrapper means workspace-write remains unLine truncated
},
{
"path": "docs/RUNTIME_SIMPLIFICATION_DESIGN.md",
"sha256": "50f637f0380c9ab05bfe71a7e863f339b0d8e218369bbb044b9b7f09138f2c59",
"content": "# Codewhale Runtime Simplification Design\n\n**Status:** Pre-implementation design record for the v0.9.1 cutover, kept for its\n\"Rejected alternatives\" provenance. It is **not** current runtime documentation\nand it shipped differently in two ways:\n\n- Goal 3 below (\"keeping every legacy tool name registered but hidden\") was\n reversed. The per-action file/git/run/web and `exec_shell*` names were\n **removed**, not hidden — `crates/tui/src/tools/registry.rs` asserts they\n must stay unregistered. Only `apply_patch` and the\n `task_*` / `github_*` / `automation_*` / `rlm_*` / `checklist_*` families\n survive as hidden aliases.\n- The default-active policy is nine names, not ten. `update_plan` and `Web` are\n not in `DEFAULT_ACTIVE_NATIVE_TOOLS`\n (`crates/tui/src/core/engine/tool_catalog.rs:44-58`).\n\nFor the current contract see [`TOOL_SURFACE.md`](TOOL_SURFACE.md).\n\n## Goal\n\nMake the model-facing runtime smaller, calmer, and easier for models to use by:\n\n1. Collapsing the long tail of single-purpose file, git, run, and web tools into\n a few canonical action-based tools.\n2. Shrinking the system prompt to durable behavioral invariants and per-turn\n permission deltas.\n3. Keeping every legacy tool name registered but hidden so old transcripts,\n saved sessions, and recorded automation replay without migration.\n\n## Target model-facing surface (default active)\n\n| Tool | Actions / Niche |\n|---|---|\n| `Bash` | `run`, `wait`, `interact`, `cancel` (existing) |\n| `File` | `read`, `list`, `search_name`, `search_content`, `write`, `edit`, `patch` |\n| `Git` | `status`, `diff`, `log`, `show`, `blame` |\n| `Run` | `tests`, `verifiers` |\n| `Web` | `search`, `fetch`, `wait` (deferred unless network is enabled; hidden aliases for legacy names) |\n| `tasks` | durable task family (existing action-based surface) |\n| `github` | durable GitHub family (existing; deferred by default) |\n| `automation` | durable automation family (existing; deferred by default) |\n| `rlm` | durable RLM family (existing; deferred by default) |\n| `agent` | sub-agent dispatch |\n| `remember` | opt-in durable user-memory capture; eager whenever registered |\n| `todo_write` | progress / plan-of-work updates |\n| `update_plan` | plan artifact updates |\n| `tool_search` | on-demand discovery of deferred tools |\n\nDefault-active policy: **10 names** (vs. ~18 before the simplification), with\n`remember` registered only for built-in-memory users and the durable families\nand `Web` discoverable via `tool_search` when needed. `tool_search` itself is a\nsynthetic always-active catalog entry.\n\n## Rejected alternatives\n\n- **Keep every tool but defer the rare ones.** This only changes what is\n advertised, not how many distinct schemas the model must learn. It also\n leaves duplicated guidance in the prompt.\n- **Route search and git through `Bash`.** `grep_files`, `file_search`, and the\n git tools return structured, workspace-aware output and respect sandbox,\n `.gitignore`, and network policy. Shell would force the model to re-parse\n free-form text and lose those guarantees, so dedicated tools win.\n- **One mega `File` tool plus a separate `Edit` tool.** A single `File` tool is\n only slightly larger than a read/edit pair and keeps the boundary the model\n already understands (`read` is cheap, `edit` requires prior read). Splitting\n would re-introduce a two-tool alias for the same underlying operations.\n- **Delete legacy tools.** Saved transcripts and replay tests rely on the old\n names. Removing them would require a config migration and break reproducibility.\n Hidden aliases avoid both.\n\n## Compatibility\n\n- Legacy names (`read_file`, `write_file`, `edit_file`, `list_dir`, `file_search`,\n `grep_files`, `apply_patch`, `git_status`, `git_diff`, `git_log`, `git_show`,\n `git_blame`, `run_tests`, `run_verifiers`, `web_search`, `fetch_url`,\n `wait_for_dev_server`) stay registered with `model_visible = false`.\n- The engine resolves calls by name, so old transcripts replay without changes.\n- `DEFAULT_ACTIVE_NATIVE_TOOLS` is updated to list the new canonical names only;\n hidden legacy tools are ignored by catalog construction.\n\n## Prompt simplification\n\n- Replace the tool-calling recipe sections in `AGENT_MODE` and\n `SUBAGENT_OUTPUT_FORMAT` with short references to the canonical tools.\n- Reduce mode deltas to permission statements (Act = write requires approval,\n Plan = no writes or shell, Full Access = auto-approved, Operate = coordinate from\n ordinary messages).\n- Keep the `BASE_PROMPT` behavioral invariants, `LANGUAGE_PROMPT`, and\n `OUTPUT_PROMPT` intact.\n- Move detailed templates (`COMPACT_TEMPLATE`, sub-agent brief format, planning\n artifact template) out of the stable prefix and into tool schemas or\n conditional blocks.\n\n## Validation\n\n- Provider-free: `scripts/measure-runtime-contract.py` reports active tool count\n and prompt bytes before and aLine truncated
},
{
"path": "docs/LSP_PHP_CUSTOM.md",
"sha256": "2dc48d7688a92844d6a5adf682e457b9bcb30f54c64c838af254d35feb4b659f",
"content": "# LSP: PHP Support & Custom Language Server Extension\n\n> 阅读简体中文版:[zh_hans/LSP_PHP_CUSTOM.md](zh_hans/LSP_PHP_CUSTOM.md)\n>\n> v0.8.65+ | `codex/lsp-php-custom-servers`\n\n## Overview\n\nThis feature adds **PHP** to the built-in LSP language registry and introduces a\n`[lsp.custom]` config section so users can register arbitrary LSP servers by\nfile extension — covering languages absent from the built-in `Language` enum\n(Ruby, C#, Swift, Lua, etc.).\n\n## Changes\n\n### 1. PHP built-in support\n\n- `Language::Php` variant added to the enum in `crates/tui/src/lsp/registry.rs`\n- `.php` files are detected and routed to `intelephense --stdio` by default\n- User can override via `[lsp.servers].php`\n\n### 2. Custom LSP server extension\n\nNew struct `CustomLspDef` (defined in `crates/tui/src/lsp/mod.rs` and mirrored\nin `crates/config/src/lib.rs`):\n\n```rust\npub struct CustomLspDef {\n pub language_id: String, // LSP languageId for textDocument/didOpen\n pub command: String, // executable to spawn\n pub args: Vec<String>, // arguments (default empty)\n}\n```\n\nNew config field `LspConfig.custom: HashMap<String, CustomLspDef>` — keyed by\nfile extension (without dot), e.g. `\"rb\"`, `\"cs\"`, `\"swift\"`.\n\nIn `LspManager::diagnostics_for`, when the built-in registry returns\n`Language::Other`, the manager checks the user's custom table before giving up.\nCustom servers get their own lazy-spawn transport map and once-per-extension\nmissing-binary warnings (no log spam).\n\n### 3. Transport generalization\n\n`StdioLspTransport::spawn` now accepts `&str language_id` instead of\n`Language`, so both built-in and custom servers share the same transport\nimplementation. The old `Language` import is removed from `client.rs`.\n\n### 4. Polling pipeline extracted\n\n`poll_diagnostics` is a new private method that both built-in and custom\ndiagnostics paths share — eliminating duplicated call/wait/filter/sort/truncate\nlogic.\n\n## Configuration\n\n### Built-in PHP (enabled by default if `intelephense` is on PATH)\n\n```toml\n# No config needed — PHP .php files are detected automatically.\n# Override the server if desired:\n[lsp.servers]\nphp = [\"phpactor\", \"language-server\"]\n```\n\n### Custom language servers\n\n```toml\n[lsp.custom.rb]\ncommand = \"ruby-lsp\"\nargs = [\"--stdio\"]\nlanguage_id = \"ruby\"\n\n[lsp.custom.cs]\ncommand = \"csharp-ls\"\nlanguage_id = \"csharp\"\n\n[lsp.custom.swift]\ncommand = \"sourcekit-lsp\"\nlanguage_id = \"swift\"\n```\n\nKeys are file extensions (no leading dot). The `args` field defaults to empty.\n`language_id` must match what the LSP server expects in `textDocument/didOpen`.\n\n## Architecture\n\n```\nedit_file / write_file / apply_patch success\n │\n ▼\n LspManager.diagnostics_for(file)\n │\n ├── custom_for_extension(file) ── found? ──► transport_for_custom(ext, def)\n │ │\n ├── detect_language(file) ── Other? ──► return None (skip)\n │\n └── transport_for(lang)\n │\n ▼\n poll_diagnostics(file, text, transport)\n │\n ▼\n DiagnosticBlock → injected into session message stream\n```\n\n## Verification\n\n```\ncargo test -p codewhale-tui --lib lsp::\n# 32 tests passed (3 new: detects_php_extension, language_ids_for_php,\n# server_for_php_is_intelephense)\ncargo clippy -p codewhale-tui --lib\n# lsp module: zero new warnings\n```\n\n## Files touched\n\n| File | Change |\n|------|--------|\n| `crates/tui/src/lsp/registry.rs` | +Php variant, detection, server mapping, tests |\n| `crates/tui/src/lsp/mod.rs` | +CustomLspDef, LspConfig.custom, LspManager custom fallback |\n| `crates/tui/src/lsp/client.rs` | spawn accepts &str language_id |\n| `crates/tui/src/config.rs` | LspConfigToml.custom + into_runtime |\n| `crates/config/src/lib.rs` | LspConfigToml.custom + CustomLspDef |\n| `config.example.toml` | PHP docs + custom extension examples |\n"
}
]
}
]
+985
View File
@@ -0,0 +1,985 @@
{
"format": "codewhale.features.v1",
"source": {
"path": "docs/features.toml",
"sha256": "0925e265468d2561e17f9799d645563757546d81f4ef001553cf1aa231329f16"
},
"features": [
{
"id": "shell-tool",
"name": "Shell tool",
"summary": "Runs shell commands for the agent through the approval gate and sandbox.",
"status": "stable",
"surfaces": {
"tui": "stable"
},
"since": "0.1.0",
"flag": "shell_tool",
"docs": "docs/TOOL_SURFACE.md",
"registryLine": 40
},
{
"id": "local-code-execution",
"name": "Local code execution",
"summary": "Runs Python and Node with the shared execution policy and explicitly approved per-call elevation.",
"status": "stable",
"surfaces": {
"tui": "stable"
},
"since": null,
"flag": null,
"docs": "docs/TOOL_SURFACE.md#local-code-execution",
"registryLine": 51
},
{
"id": "subagents",
"name": "Sub-agents",
"summary": "Delegates bounded work to background child agents with their own budgets.",
"status": "stable",
"surfaces": {
"tui": "stable",
"api": "stable"
},
"since": "0.1.0",
"flag": "subagents",
"docs": "docs/SUBAGENTS.md",
"registryLine": 60
},
{
"id": "web-search",
"name": "Web search",
"summary": "Searches and fetches the web for the agent (web.run, with the web_search alias).",
"status": "stable",
"surfaces": {
"tui": "stable"
},
"since": "0.1.0",
"flag": "web_search",
"docs": "docs/TOOL_SURFACE.md",
"registryLine": 71
},
{
"id": "apply-patch",
"name": "apply_patch",
"summary": "Edits files with structured patches the user can review and undo.",
"status": "stable",
"surfaces": {
"tui": "stable"
},
"since": "0.1.0",
"flag": "apply_patch",
"docs": "docs/TOOL_SURFACE.md",
"registryLine": 82
},
{
"id": "mcp-client",
"name": "MCP client",
"summary": "Connects local stdio and remote HTTP MCP servers and exposes their tools.",
"status": "stable",
"surfaces": {
"tui": "stable",
"api": "stable"
},
"since": "0.1.0",
"flag": "mcp",
"docs": "docs/MCP.md",
"registryLine": 93
},
{
"id": "exec-policy",
"name": "Execution policy",
"summary": "Decides allow, ask or deny for each tool call from layered permission rules.",
"status": "stable",
"surfaces": {
"tui": "stable"
},
"since": "0.1.0",
"flag": "exec_policy",
"docs": "docs/AUTHORIZATION_ORDER.md",
"registryLine": 104
},
{
"id": "vision-model",
"name": "Vision model",
"summary": "Routes image analysis to a separate vision-capable model configured in [vision_model].",
"status": "flagged",
"surfaces": {
"tui": "stable"
},
"since": "0.8.32",
"flag": "vision_model",
"docs": "docs/CONFIGURATION.md",
"registryLine": 115
},
{
"id": "verify-tool",
"name": "verify tool",
"summary": "Lets the agent ask for an adversarial self-critique of its own work.",
"status": "stable",
"surfaces": {
"tui": "stable"
},
"since": "0.9.2",
"flag": "verify_tool",
"docs": "docs/CONFIGURATION.md#feature-flags",
"registryLine": 126
},
{
"id": "code-mode",
"name": "Code mode",
"summary": "execute_tools programs compose MCP, plugin and native tool calls under the normal gate.",
"status": "experimental",
"surfaces": {
"tui": "stable"
},
"since": "0.10.0",
"flag": "code_mode",
"docs": "docs/TOOL_SURFACE.md#code-mode-execute_tools",
"registryLine": 137
},
{
"id": "extension-host",
"name": "Extension host",
"summary": "Runs reviewed plugins' native TypeScript/JavaScript tool and slash-command code in a Bun or Node sidecar.",
"status": "flagged",
"surfaces": {
"tui": "preview",
"web": "none",
"api": "none"
},
"since": "0.10.1",
"flag": "extension_host",
"docs": "docs/EXTENSIONS.md",
"registryLine": 148
},
{
"id": "finance-host",
"name": "Finance host",
"summary": "Routes opted-in finance tools through the bundled Native host under the existing permission and sandbox gates.",
"status": "flagged",
"surfaces": {
"tui": "preview",
"api": "preview"
},
"since": "0.10.1",
"flag": "finance_host",
"docs": "docs/TOOL_SURFACE.md",
"registryLine": 159
},
{
"id": "data-host",
"name": "Data host",
"summary": "Routes opted-in data validation through the bundled Native host with owned input and output bounds.",
"status": "flagged",
"surfaces": {
"tui": "preview",
"api": "preview"
},
"since": "0.10.1",
"flag": "data_host",
"docs": "docs/TOOL_SURFACE.md",
"registryLine": 170
},
{
"id": "speech-host",
"name": "Speech host",
"summary": "Routes opted-in speech tools through the bundled Native host while Rust retains credentials and permissions.",
"status": "flagged",
"surfaces": {
"tui": "preview",
"api": "preview"
},
"since": "0.10.1",
"flag": "speech_host",
"docs": "docs/TOOL_SURFACE.md",
"registryLine": 181
},
{
"id": "pdf-host",
"name": "PDF host",
"summary": "Routes opted-in PDF extraction through the bundled Native host with the same Rust path and size guards.",
"status": "flagged",
"surfaces": {
"tui": "preview",
"api": "preview"
},
"since": "0.10.1",
"flag": "pdf_host",
"docs": "docs/TOOL_SURFACE.md",
"registryLine": 192
},
{
"id": "ocr-host",
"name": "OCR host",
"summary": "Routes opted-in image OCR through the bundled Native host under existing media and permission guards.",
"status": "flagged",
"surfaces": {
"tui": "preview",
"api": "preview"
},
"since": "0.10.1",
"flag": "ocr_host",
"docs": "docs/TOOL_SURFACE.md",
"registryLine": 203
},
{
"id": "github-host",
"name": "GitHub host",
"summary": "Routes opted-in GitHub operations through the bundled Native host while Rust retains credentials and approvals.",
"status": "flagged",
"surfaces": {
"tui": "preview",
"api": "preview"
},
"since": "0.10.1",
"flag": "github_host",
"docs": "docs/TOOL_SURFACE.md",
"registryLine": 214
},
{
"id": "web-search-host",
"name": "Web search host",
"summary": "Routes opted-in web search through the bundled Native host with the existing Rust credential and network gates.",
"status": "flagged",
"surfaces": {
"tui": "preview",
"api": "preview"
},
"since": "0.10.1",
"flag": "web_search_host",
"docs": "docs/TOOL_SURFACE.md",
"registryLine": 225
},
{
"id": "web-extract-host",
"name": "Web extract host",
"summary": "Routes opted-in web extraction through the bundled Native host with owned URL and response bounds.",
"status": "flagged",
"surfaces": {
"tui": "preview",
"api": "preview"
},
"since": "0.10.1",
"flag": "web_extract_host",
"docs": "docs/TOOL_SURFACE.md",
"registryLine": 236
},
{
"id": "review-host",
"name": "Review host",
"summary": "Routes opted-in review tools through the bundled Native host while Rust retains route and permission authority.",
"status": "flagged",
"surfaces": {
"tui": "preview",
"api": "preview"
},
"since": "0.10.1",
"flag": "review_host",
"docs": "docs/TOOL_SURFACE.md",
"registryLine": 247
},
{
"id": "modes",
"name": "Modes",
"summary": "Plan, Work and Operate modes set what the agent may do in a session; a finished plan offers to start the work.",
"status": "stable",
"surfaces": {
"tui": "stable",
"api": "stable"
},
"since": null,
"flag": null,
"docs": "docs/MODES.md",
"registryLine": 260
},
{
"id": "permission-postures",
"name": "Permission postures",
"summary": "Ask, Auto-Review and Full Access postures decide when a tool call needs approval.",
"status": "stable",
"surfaces": {
"tui": "stable",
"api": "stable"
},
"since": null,
"flag": null,
"docs": "docs/MODES.md#permission-posture",
"registryLine": 269
},
{
"id": "sandbox",
"name": "Command sandbox",
"summary": "Wraps commands in Seatbelt on macOS; bubblewrap on Linux is on by default once installed and verified.",
"status": "stable",
"surfaces": {
"tui": "stable"
},
"since": null,
"flag": null,
"docs": "docs/SANDBOX.md",
"registryLine": 278
},
{
"id": "providers",
"name": "Providers",
"summary": "First-class provider routes plus bundled OpenAI-compatible host descriptors.",
"status": "stable",
"surfaces": {
"tui": "stable",
"api": "stable"
},
"since": null,
"flag": null,
"docs": "docs/PROVIDERS.md",
"registryLine": 287
},
{
"id": "model-routing",
"name": "Auto model routing",
"summary": "Picks a model per turn under Auto; /router sets up the router.",
"status": "stable",
"surfaces": {
"tui": "stable"
},
"since": null,
"flag": null,
"docs": "docs/CONFIGURATION.md#auto-model-routing-auto-autorouter",
"registryLine": 296
},
{
"id": "fleet",
"name": "Fleet",
"summary": "Runs and supervises groups of worker agents with receipts and a pre-spend check.",
"status": "stable",
"surfaces": {
"tui": "stable",
"api": "stable"
},
"since": null,
"flag": null,
"docs": "docs/FLEET.md",
"registryLine": 305
},
{
"id": "workflows",
"name": "Workflows",
"summary": "Checked-in .workflow.js scripts coordinate agents step by step.",
"status": "stable",
"surfaces": {
"tui": "stable"
},
"since": null,
"flag": null,
"docs": "docs/WORKFLOW_AUTHORING.md",
"registryLine": 314
},
{
"id": "automatic-workflows",
"name": "Automatic workflows",
"summary": "Turns a broad request into a compact Workflow plan without writing a script.",
"status": "stable",
"surfaces": {
"tui": "stable"
},
"since": null,
"flag": null,
"docs": "docs/AUTOMATIC_WORKFLOWS.md",
"registryLine": 323
},
{
"id": "goals",
"name": "Goals",
"summary": "/goal keeps the agent working toward one objective across turns.",
"status": "stable",
"surfaces": {
"tui": "stable",
"api": "stable"
},
"since": null,
"flag": null,
"docs": "docs/CONFIGURATION.md#goal-loop-goal",
"registryLine": 332
},
{
"id": "todos",
"name": "Todo list",
"summary": "The agent keeps a visible todo list for multi-step work.",
"status": "stable",
"surfaces": {
"tui": "stable",
"api": "stable"
},
"since": null,
"flag": null,
"docs": "docs/TOOL_SURFACE.md",
"registryLine": 341
},
{
"id": "composer-queue-steer",
"name": "Queue and steer",
"summary": "Queue messages while a turn runs, or steer the running turn.",
"status": "stable",
"surfaces": {
"tui": "stable",
"api": "stable"
},
"since": null,
"flag": null,
"docs": "docs/KEYBINDINGS.md",
"registryLine": 350
},
{
"id": "receipts",
"name": "Receipts",
"summary": "/receipts lists what a session did: files, commands, calls, approvals and failures.",
"status": "stable",
"surfaces": {
"tui": "stable",
"api": "stable"
},
"since": "0.10.1",
"flag": null,
"docs": "docs/RECEIPTS.md",
"registryLine": 359
},
{
"id": "preview-request",
"name": "Request preview",
"summary": "/preview-request shows the redacted outbound request without sending it.",
"status": "stable",
"surfaces": {
"tui": "stable"
},
"since": null,
"flag": null,
"docs": "docs/PREVIEW_REQUEST.md",
"registryLine": 369
},
{
"id": "read-media",
"name": "read_media",
"summary": "Reads and preprocesses images for vision-capable models with size and privacy guards.",
"status": "stable",
"surfaces": {
"tui": "stable"
},
"since": null,
"flag": null,
"docs": "docs/READ_MEDIA.md",
"registryLine": 378
},
{
"id": "memory",
"name": "User memory",
"summary": "Opt-in local store of preferences and conventions that persists across sessions.",
"status": "flagged",
"surfaces": {
"tui": "stable",
"api": "stable"
},
"since": null,
"flag": null,
"docs": "docs/MEMORY.md",
"registryLine": 387
},
{
"id": "skills",
"name": "Skills",
"summary": "Installs and loads trusted instruction packages with owned-root precedence and separate user/model invocation controls.",
"status": "stable",
"surfaces": {
"tui": "stable",
"api": "stable"
},
"since": null,
"flag": null,
"docs": "docs/SKILLS.md",
"registryLine": 398
},
{
"id": "plugins",
"name": "Plugins",
"summary": "Installs, reviews and trusts plugin bundles, including the first-party marketplace.",
"status": "stable",
"surfaces": {
"tui": "stable",
"api": "stable"
},
"since": null,
"flag": null,
"docs": "docs/PLUGINS.md",
"registryLine": 407
},
{
"id": "computer-use",
"name": "Computer Use",
"summary": "Reviewed app control with consent, fresh element targets, observation diffs and bounded named action batches.",
"status": "experimental",
"surfaces": {
"tui": "preview",
"api": "preview"
},
"since": null,
"flag": null,
"docs": "docs/PLUGIN_BUNDLES.md",
"registryLine": 416
},
{
"id": "script-tools",
"name": "Script tools",
"summary": "Scripts in ~/.codewhale/tools become approval-gated tools; [tools.overrides] disables built-ins, never replaces them.",
"status": "stable",
"surfaces": {
"tui": "stable"
},
"since": null,
"flag": null,
"docs": "docs/CONFIGURATION.md#script-tools-and-overrides",
"registryLine": 425
},
{
"id": "claude-plugin-compat",
"name": "Claude plugin compatibility",
"summary": "Loads Claude Code plugin bundles and skill folders where their features are supported.",
"status": "stable",
"surfaces": {
"tui": "stable"
},
"since": null,
"flag": null,
"docs": "docs/CLAUDE_PLUGIN_COMPAT.md",
"registryLine": 434
},
{
"id": "claude-settings-import",
"name": "Claude settings import",
"summary": "/import-claude plans a reviewable import of Claude Code settings and servers.",
"status": "stable",
"surfaces": {
"tui": "stable"
},
"since": null,
"flag": null,
"docs": null,
"registryLine": 443
},
{
"id": "hooks",
"name": "Hooks",
"summary": "Runs user commands on session and tool events, with an execution receipt after shell tools.",
"status": "stable",
"surfaces": {
"tui": "stable",
"api": "stable"
},
"since": null,
"flag": null,
"docs": "docs/HOOKS.md",
"registryLine": 451
},
{
"id": "lsp",
"name": "LSP diagnostics",
"summary": "Feeds language-server diagnostics to the agent; custom servers can be added.",
"status": "stable",
"surfaces": {
"tui": "stable",
"api": "stable"
},
"since": null,
"flag": null,
"docs": "docs/LSP_PHP_CUSTOM.md",
"registryLine": 460
},
{
"id": "runtime-api",
"name": "Runtime API",
"summary": "Local HTTP API for threads, events and approvals, with scoped watch/drive device tokens and account-bound model turns.",
"status": "stable",
"surfaces": {
"api": "stable"
},
"since": null,
"flag": null,
"docs": "docs/RUNTIME_API.md",
"registryLine": 469
},
{
"id": "headless-exec",
"name": "Headless exec",
"summary": "codewhale exec runs one headless turn from a script and streams JSON.",
"status": "stable",
"surfaces": {
"tui": "stable"
},
"since": null,
"flag": null,
"docs": "docs/RUNTIME_API.md",
"registryLine": 478
},
{
"id": "github-review",
"name": "GitHub PR review",
"summary": "codewhale review --pr N writes an advisory review; posting to GitHub is opt-in.",
"status": "stable",
"surfaces": {
"tui": "stable"
},
"since": null,
"flag": null,
"docs": "docs/GITHUB_APP.md",
"registryLine": 487
},
{
"id": "web-client",
"name": "Local browser client",
"summary": "codewhale web opens the embedded browser client on 127.0.0.1 over the Runtime API.",
"status": "stable",
"surfaces": {
"web": "stable"
},
"since": null,
"flag": null,
"docs": "docs/WEB.md",
"registryLine": 498
},
{
"id": "keybindings",
"name": "Keybindings",
"summary": "Terminal key bindings, documented from the keybinding catalog.",
"status": "stable",
"surfaces": {
"tui": "stable"
},
"since": null,
"flag": null,
"docs": "docs/KEYBINDINGS.md",
"registryLine": 507
},
{
"id": "settings",
"name": "Settings",
"summary": "/config and codewhale config edit settings declared once in the settings schema.",
"status": "stable",
"surfaces": {
"tui": "stable",
"api": "stable"
},
"since": null,
"flag": null,
"docs": "docs/CONFIGURATION.md",
"registryLine": 516
},
{
"id": "themes",
"name": "Themes",
"summary": "/theme picks a built-in theme; user themes follow a JSON schema.",
"status": "stable",
"surfaces": {
"tui": "stable"
},
"since": null,
"flag": null,
"docs": "docs/schemas/user-theme.schema.json",
"registryLine": 525
},
{
"id": "localization",
"name": "Localization",
"summary": "Interface text in 15 locales.",
"status": "stable",
"surfaces": {
"tui": "stable"
},
"since": null,
"flag": null,
"docs": "docs/LOCALIZATION.md",
"registryLine": 534
},
{
"id": "voice",
"name": "Voice input",
"summary": "/voice, /voicecontrol and /voicesend use the selected ASR backend without switching providers.",
"status": "stable",
"surfaces": {
"tui": "stable",
"api": "stable"
},
"since": null,
"flag": null,
"docs": null,
"registryLine": 543
},
{
"id": "pet",
"name": "Pet",
"summary": "A per-terminal whale view of working, waiting, done and failed; Ctrl+] cycles its views, F5 opens replies and agents.",
"status": "stable",
"surfaces": {
"tui": "stable"
},
"since": null,
"flag": null,
"docs": "docs/PET_MODE.md",
"registryLine": 551
},
{
"id": "overview",
"name": "Home dashboard",
"summary": "/overview shows the home dashboard.",
"status": "stable",
"surfaces": {
"tui": "stable"
},
"since": null,
"flag": null,
"docs": "docs/PROVIDERS.md",
"registryLine": 560
},
{
"id": "account-login",
"name": "Account login",
"summary": "/login signs in to Codewhale or stores provider keys; plugin providers connect with /connect.",
"status": "stable",
"surfaces": {
"tui": "stable"
},
"since": null,
"flag": null,
"docs": null,
"registryLine": 569
},
{
"id": "account-computer-files",
"name": "Account computer files",
"summary": "Save computer files as account versions, restore with revision checks, and download verified bytes.",
"status": "experimental",
"surfaces": {
"tui": "preview"
},
"since": "unreleased",
"flag": null,
"docs": null,
"registryLine": 577
},
{
"id": "context-anchors",
"name": "Context anchors",
"summary": "/anchor pins a fact that survives compaction.",
"status": "stable",
"surfaces": {
"tui": "stable"
},
"since": null,
"flag": null,
"docs": null,
"registryLine": 586
},
{
"id": "window-pin",
"name": "Pin window",
"summary": "/pin keeps the terminal window on top.",
"status": "stable",
"surfaces": {
"tui": "stable"
},
"since": null,
"flag": null,
"docs": null,
"registryLine": 594
},
{
"id": "structured-copy",
"name": "Structured copy",
"summary": "/structcopy copies one session object as redacted JSON.",
"status": "stable",
"surfaces": {
"tui": "stable"
},
"since": null,
"flag": null,
"docs": null,
"registryLine": 602
},
{
"id": "live-thinking",
"name": "Live thinking",
"summary": "/verbose toggles live model thinking in the transcript.",
"status": "stable",
"surfaces": {
"tui": "stable"
},
"since": null,
"flag": null,
"docs": null,
"registryLine": 610
},
{
"id": "workbar",
"name": "Workbar",
"summary": "/workbar places the tasks, agents and context bar on any edge or hides it.",
"status": "stable",
"surfaces": {
"tui": "stable"
},
"since": null,
"flag": null,
"docs": null,
"registryLine": 618
},
{
"id": "terminal-dock",
"name": "Terminal dock",
"summary": "/workbar terminal shows workspace PTYs with live output, human input, session selection and a fresh shell; macOS/Linux.",
"status": "stable",
"surfaces": {
"tui": "stable"
},
"since": null,
"flag": null,
"docs": null,
"registryLine": 626
},
{
"id": "telemetry",
"name": "Telemetry",
"summary": "Anonymous aggregate usage counts, disclosed at first launch, with a saved off switch.",
"status": "stable",
"surfaces": {
"tui": "stable"
},
"since": null,
"flag": null,
"docs": "docs/TELEMETRY.md",
"registryLine": 636
},
{
"id": "docker",
"name": "Docker image",
"summary": "Runs Codewhale in a container, with an opt-in toolbox image.",
"status": "stable",
"surfaces": {
"tui": "stable"
},
"since": null,
"flag": null,
"docs": "docs/DOCKER.md",
"registryLine": 645
},
{
"id": "termux",
"name": "Android (Termux)",
"summary": "arm64 release archive for Termux on Android.",
"status": "experimental",
"surfaces": {
"tui": "preview"
},
"since": null,
"flag": null,
"docs": "docs/TERMUX.md",
"registryLine": 654
},
{
"id": "chatgpt-plan-sign-in",
"name": "Sign in with ChatGPT",
"summary": "Uses official OAuth and the selected account catalog for eligible ChatGPT plan requests in the local OSS app.",
"status": "experimental",
"surfaces": {
"tui": "preview",
"api": "partial",
"web": "none"
},
"since": "unreleased",
"flag": null,
"docs": "docs/PROVIDERS.md#sign-in-with-chatgpt",
"registryLine": 663
},
{
"id": "claude-plan-sign-in",
"name": "Sign in with Claude",
"summary": "Adds Claude subscription sign-in and native Messages routing. Live provider acceptance remains unverified.",
"status": "experimental",
"surfaces": {
"tui": "preview",
"api": "partial",
"web": "none"
},
"since": "unreleased",
"flag": null,
"docs": "docs/PROVIDERS.md#sign-in-with-claude",
"registryLine": 673
},
{
"id": "plugin-oauth-providers",
"name": "Reviewed plugin OAuth providers",
"summary": "Reviewed plugins sign in with /connect <id> and out with /disconnect; the host owns PKCE, models and approvals.",
"status": "experimental",
"surfaces": {
"tui": "preview",
"api": "partial",
"web": "none"
},
"since": "unreleased",
"flag": null,
"docs": "docs/PLUGIN_PROVIDERS.md",
"registryLine": 683
},
{
"id": "orcarouter-sign-in",
"name": "Sign in with OrcaRouter",
"summary": "OrcaRouter provider: sk-orca- API key or OAuth 2.0 + PKCE sign-in, plus a live chat model catalog.",
"status": "experimental",
"surfaces": {
"tui": "preview",
"api": "none",
"web": "none"
},
"since": "unreleased",
"flag": null,
"docs": "docs/PROVIDERS.md",
"registryLine": 693
},
{
"id": "merch-interest",
"name": "Merch interest list",
"summary": "The community website collects private merch opt-ins, material preferences and optional item-price feedback.",
"status": "experimental",
"surfaces": {
"tui": "none",
"web": "none",
"api": "none"
},
"since": "unreleased",
"flag": null,
"docs": "web/lib/merch/README.md",
"registryLine": 704
},
{
"id": "profile-constitution",
"name": "Profile constitution",
"summary": "Account preferences are captured per turn and previewed by the Engine.",
"status": "experimental",
"surfaces": {
"tui": "preview",
"api": "preview"
},
"since": "unreleased",
"flag": null,
"docs": "docs/RUNTIME_API.md#profile-constitution",
"registryLine": 714
},
{
"id": "plugin-shell-install",
"name": "Plugin shell installation",
"summary": "codewhale install uses the reviewed bundle installer with local, GitHub and version-pinned npm sources.",
"status": "experimental",
"surfaces": {
"tui": "preview"
},
"since": "unreleased",
"flag": null,
"docs": "docs/PLUGINS.md",
"registryLine": 724
}
]
}
+192 -7
View File
@@ -1,4 +1,150 @@
{
"features": {
"title": "Check what Codewhale ships",
"description": "Browse Codewhale commands, tools and Runtime capabilities with availability and documentation.",
"notice": "This catalogue covers {count} entries in source v{version}. Names and descriptions are in English; check your installed version.",
"stable": "Stable",
"flagged": "Requires a flag",
"experimental": "Experimental",
"partial": "Partial",
"preview": "Preview",
"none": "Unavailable",
"docs": "Read documentation",
"source": "Read source entry",
"exportJson": "Download feature JSON"
},
"docs-skills": {
"metaTitle": "Manage skills · Codewhale Docs",
"metaDescription": "Find, install and trust SKILL.md instruction packages. Control user and model invocation and import compatible Claude Code skills.",
"bodyClassName": "text-ink-soft leading-relaxed",
"title": "Manage reusable skills",
"lede": "Skills are SKILL.md instruction packages. Discover compatible folders, then review the source and trust before using a skill.",
"sections": [
{
"id": "manager",
"title": "Open the skills manager",
"blocks": [
{
"code": "/skills\n/skills manage\n/skills inspect\n/skill <name>",
"lang": "Codewhale"
},
{
"p": "The manager opens without network access and shows owned roots. Turn on compatible-root scanning to inspect external folders; importing targets a Codewhale-owned root."
}
]
},
{
"id": "install",
"title": "Install into an owned folder",
"blocks": [
{
"code": "/skill install --project <spec>\n/skill install --global <spec>\n/skill trust --project <name>",
"lang": "Codewhale"
},
{
"p": "Owned roots are .codewhale/skills in your project and ~/.codewhale/skills globally. Compatible .agents/skills and .claude/skills directories are read-only import sources."
},
{
"note": "Project skills load only after you trust that workspace. A configured external skills_dir stays read-only; choosing a folder does not grant authority to mutate it."
}
]
},
{
"id": "invocation",
"title": "Choose who can load a skill",
"blocks": [
{
"p": "Frontmatter disable-model-invocation: true removes a skill from model discovery. user-invocable: false hides it from user menus and refuses explicit activation; setting both disables both paths."
},
{
"p": "A skill body enters context when loaded. The compact catalogue contains bounded names, aliases and invocation metadata."
}
]
}
],
"next": [
{
"href": "/docs/claude-code",
"label": "Move from Claude Code",
"note": "Bring compatible skills and review a settings import."
},
{
"href": "/plugins",
"label": "Add plugins",
"note": "Install supported bundles through review and trust."
}
],
"sourceNote": "Source: docs/SKILLS.md and docs/CLAUDE_PLUGIN_COMPAT.md."
},
"docs-claude-code": {
"metaTitle": "Move from Claude Code · Codewhale Docs",
"metaDescription": "Use Codewhale as an open-source Claude Code alternative. Bring compatible instructions and skills, and review a settings and MCP import plan.",
"bodyClassName": "text-ink-soft leading-relaxed",
"title": "Move from Claude Code",
"lede": "Keep compatible project instructions and skill folders while choosing your own model connection. Review settings and plugin imports before applying them.",
"sections": [
{
"id": "instructions",
"title": "Keep your project instructions",
"blocks": [
{
"p": "AGENTS.md is the canonical project instruction file. CLAUDE.md and .claude/instructions.md are compatibility fallbacks; they do not override Codewhale security controls."
},
{
"p": "Plain .claude/skills/<name>/SKILL.md folders are discovered through the normal [skills registry](/docs/skills), with workspace trust and invocation controls."
}
]
},
{
"id": "settings",
"title": "Review a settings import",
"blocks": [
{
"code": "/import-claude",
"lang": "Codewhale"
},
{
"p": "The command reads Claude settings and writes a reviewable report and unapplied config bundle. MCP servers use the existing import consent flow; permissions and hooks need separate review."
},
{
"note": "Secret-shaped and unknown environment values are not imported or echoed. Running the plan does not enable servers or apply permissions."
}
]
},
{
"id": "plugins",
"title": "Install the supported plugin subset",
"blocks": [
{
"code": "/plugin install <spec>",
"lang": "Codewhale"
},
{
"p": "The declarative .claude-plugin/plugin.json subset supports skills, commands, agent profiles and MCP declarations. Codewhale review hashes and explicit trust and enablement still apply."
},
{
"note": "Codewhale does not run Claude Code plugin runtimes. Hooks, plugin LSP declarations, build steps and TypeScript agents are outside this importer."
},
{
"p": "[Read the compatibility limits](https://github.com/codewhale-hq/CodeWhale/blob/main/docs/CLAUDE_PLUGIN_COMPAT.md). Choose credentials and endpoints in [model setup](/models)."
}
]
}
],
"next": [
{
"href": "/docs/skills",
"label": "Manage skills",
"note": "Inspect compatible directories before importing."
},
{
"href": "/docs/auth",
"label": "Connect a provider",
"note": "Use your chosen hosted or local model."
}
],
"sourceNote": "Source: docs/CONFIGURATION.md, docs/CLAUDE_PLUGIN_COMPAT.md and the claude-settings-import entry in docs/features.toml."
},
"chrome": {
"navDocs": "Docs",
"navStart": "Start",
@@ -6,6 +152,7 @@
"navFaq": "FAQ",
"navCommunity": "Community",
"navContribute": "Contribute",
"navFeatures": "Capabilities",
"navProduct": "Product",
"navModels": "Models",
"navPlugins": "Plugins",
@@ -46,10 +193,10 @@
"partialBadge": "(partial)"
},
"home": {
"metaTitle": "Codewhale: build with your models and tools",
"metaDescription": "Build apps, automate workflows, and work across connected tools with Codewhale. Open source, with your own model APIs or local and self-hosted inference.",
"metaTitle": "Codewhale: an open-source coding agent",
"metaDescription": "Codewhale is an open-source coding agent for your terminal. Read, edit and test projects with your own hosted or local models.",
"heroTitle": "Build apps and automate your work.",
"heroIntro": "{brand} is an open-source agent that writes code, runs commands and works with the tools you connect. Use your existing model APIs, or run models locally and on your own servers.",
"heroIntro": "{brand} is an open-source coding agent that reads files, writes code and runs commands in your terminal. Connect your existing model API or a local model, and choose which actions need approval.",
"getCodewhale": "Install Codewhale",
"heroInstallAria": "Install command",
"exploreProduct": "Explore Codewhale",
@@ -874,14 +1021,14 @@
"title": "Run Codewhale as an MCP server",
"blocks": [
{
"p": "Other MCP clients — including another Codewhale session — can use Codewhale's tools. Register it once:"
"p": "Other MCP clients can use Codewhale as a tool server. By default, it exposes only read-only `file_read` and `search` tools."
},
{
"code": "codewhale mcp add-self\ncodewhale mcp tools codewhale",
"lang": "Terminal"
},
{
"p": "`add-self` writes an entry that runs `codewhale serve --mcp` over stdio. Each client starts its own process; no network port is opened. `codewhale serve --http` is a different thing — the [Runtime API](/docs/runtime-api) for apps."
"p": "`add-self` registers `codewhale serve --mcp` over stdio; `codewhale mcp-server` is the equivalent entry point. Write tools stay withheld unless the operator explicitly permits them in server configuration. [Runtime API](/docs/runtime-api) HTTP is a separate transport."
}
]
},
@@ -1190,6 +1337,25 @@
"title": "Limit what commands can touch",
"lede": "Approving a command decides whether it runs. A sandbox decides what it can reach once it does. Codewhale uses the operating system's sandbox where one is available and tells you plainly when there is none.",
"sections": [
{
"id": "execution-policy",
"title": "Inspect execution policy rules",
"blocks": [
{
"code": "/permissions",
"lang": "Codewhale"
},
{
"p": "Typed permissions select User, Agent and BuiltinDefault rules in that order. Within one source layer, deny wins over ask and allow; specificity breaks ties."
},
{
"p": "Hard denied command prefixes cannot be overridden by a typed allow. An allow never removes later safety checks, repository restrictions or sandbox limits."
},
{
"p": "[Read the authorization order and matching rules](https://github.com/codewhale-hq/CodeWhale/blob/main/docs/AUTHORIZATION_ORDER.md)"
}
]
},
{
"id": "platforms",
"title": "Check what your platform provides",
@@ -1759,6 +1925,25 @@
"title": "See what leaves your machine",
"lede": "Codewhale runs on your computer and talks to the model provider you choose. This page lists what goes where, what the anonymous usage count contains, and how to switch it off — as built today.",
"sections": [
{
"id": "preview-request",
"title": "See the request before sending",
"blocks": [
{
"p": "/preview-request shows a redacted manifest of the next primary turn. This human command never sends a request or writes conversation or Work state."
},
{
"code": "/preview-request\n/preview-request json\n/preview-request json --prompt explain this project",
"lang": "Codewhale"
},
{
"note": "Without --prompt, route and body are unavailable. A configured classifier, hooks or pending runtime work can also prevent an exact preview; the manifest states why."
},
{
"p": "[Read the request preview contract](https://github.com/codewhale-hq/CodeWhale/blob/main/docs/PREVIEW_REQUEST.md)"
}
]
},
{
"id": "boundaries",
"title": "Where your work goes",
@@ -1926,8 +2111,8 @@
"emptyBody": "The build did not find a parsable CHANGELOG.md. The GitHub release list is still the record."
},
"computer-use": {
"metaTitle": "Computer Use for Mac · Codewhale",
"metaDescription": "Download and set up Codewhale Computer Use for Mac. Background app control, permission setup, and human Pause and Stop controls.",
"metaTitle": "Computer Use · Preview · Codewhale",
"metaDescription": "Preview: download and set up Codewhale Computer Use for Mac. Background app control, permission setup, and human Pause and Stop controls.",
"title": "Computer Use",
"lead": "Let Codewhale work in your apps while you keep working. The Mac helper brings permissions, background app control, and a way to pause or stop input to your menu bar.",
"publisher": "By Codewhale",
+192 -7
View File
@@ -1,4 +1,150 @@
{
"features": {
"title": "查看 Codewhale 提供的能力",
"description": "浏览 Codewhale 命令、工具和 Runtime 能力,了解可用范围并查看文档。",
"notice": "本目录包含源码 v{version} 中的 {count} 项能力。名称与说明使用英文;请核对已安装版本。",
"stable": "稳定",
"flagged": "需要功能开关",
"experimental": "实验性",
"partial": "部分支持",
"preview": "预览",
"none": "不可用",
"docs": "阅读文档",
"source": "查看源码条目",
"exportJson": "下载功能 JSON"
},
"docs-skills": {
"metaTitle": "管理技能 · Codewhale 文档",
"metaDescription": "查找、安装并信任 SKILL.md 指令包,控制用户与模型调用,并导入兼容的 Claude Code 技能。",
"bodyClassName": "text-ink-soft leading-[1.9] tracking-wide",
"title": "管理可复用技能",
"lede": "技能是 SKILL.md 指令包。发现兼容文件夹后,先审阅来源与信任设置,再使用技能。",
"sections": [
{
"id": "manager",
"title": "打开技能管理器",
"blocks": [
{
"code": "/skills\n/skills manage\n/skills inspect\n/skill <name>",
"lang": "Codewhale"
},
{
"p": "管理器打开时不访问网络,并显示 Codewhale 自有目录。启用兼容目录扫描即可检查外部文件夹;导入目标始终是 Codewhale 自有目录。"
}
]
},
{
"id": "install",
"title": "安装到自有目录",
"blocks": [
{
"code": "/skill install --project <spec>\n/skill install --global <spec>\n/skill trust --project <name>",
"lang": "Codewhale"
},
{
"p": "自有目录包括项目中的 .codewhale/skills 与全局 ~/.codewhale/skills。兼容的 .agents/skills 和 .claude/skills 目录只作为只读导入来源。"
},
{
"note": "只有信任工作区后才会加载项目技能。配置的外部 skills_dir 始终只读;选择文件夹不会授予修改权限。"
}
]
},
{
"id": "invocation",
"title": "选择谁可以加载技能",
"blocks": [
{
"p": "Frontmatter 中的 disable-model-invocation: true 会将技能移出模型发现列表。user-invocable: false 会从用户菜单中隐藏技能并拒绝显式激活;两者同时设置会禁用两条路径。"
},
{
"p": "技能正文在加载时才进入上下文。精简目录只包含有界的名称、别名和调用元数据。"
}
]
}
],
"next": [
{
"href": "/docs/claude-code",
"label": "从 Claude Code 迁移",
"note": "带入兼容技能并审阅设置导入方案。"
},
{
"href": "/plugins",
"label": "添加插件",
"note": "通过审阅与信任流程安装支持的插件包。"
}
],
"sourceNote": "来源:docs/SKILLS.md 与 docs/CLAUDE_PLUGIN_COMPAT.md。"
},
"docs-claude-code": {
"metaTitle": "从 Claude Code 迁移 · Codewhale 文档",
"metaDescription": "把 Codewhale 作为开源 Claude Code 替代方案。保留兼容指令与技能,并审阅设置和 MCP 导入方案。",
"bodyClassName": "text-ink-soft leading-[1.9] tracking-wide",
"title": "从 Claude Code 迁移",
"lede": "保留兼容的项目说明与技能文件夹,同时选择你自己的模型连接。应用设置和插件导入前,请先审阅。",
"sections": [
{
"id": "instructions",
"title": "保留项目说明",
"blocks": [
{
"p": "AGENTS.md 是项目说明的规范文件。CLAUDE.md 和 .claude/instructions.md 作为兼容回退,不会覆盖 Codewhale 安全控制。"
},
{
"p": "普通 .claude/skills/<name>/SKILL.md 文件夹通过常规[技能注册表](/docs/skills)发现,并受工作区信任与调用控制约束。"
}
]
},
{
"id": "settings",
"title": "审阅设置导入",
"blocks": [
{
"code": "/import-claude",
"lang": "Codewhale"
},
{
"p": "该命令读取 Claude 设置,生成可审阅报告与尚未应用的配置包。MCP 服务器使用现有的导入同意流程;权限和钩子需要单独审阅。"
},
{
"note": "疑似密钥和未知环境变量的值不会被导入或回显。运行方案不会启用服务器,也不会应用权限。"
}
]
},
{
"id": "plugins",
"title": "安装支持的插件子集",
"blocks": [
{
"code": "/plugin install <spec>",
"lang": "Codewhale"
},
{
"p": "声明式 .claude-plugin/plugin.json 子集支持技能、命令、智能体配置与 MCP 声明。Codewhale 的审阅哈希、显式信任与启用流程仍然适用。"
},
{
"note": "Codewhale 不会运行 Claude Code 插件运行时。钩子、插件 LSP 声明、构建步骤与 TypeScript 智能体不在该导入器的支持范围内。"
},
{
"p": "[阅读兼容性限制](https://github.com/codewhale-hq/CodeWhale/blob/main/docs/CLAUDE_PLUGIN_COMPAT.md)。在[模型设置](/models)中选择凭据与端点。"
}
]
}
],
"next": [
{
"href": "/docs/skills",
"label": "管理技能",
"note": "导入前检查兼容目录。"
},
{
"href": "/docs/auth",
"label": "连接提供商",
"note": "使用你选择的托管模型或本地模型。"
}
],
"sourceNote": "来源:docs/CONFIGURATION.md、docs/CLAUDE_PLUGIN_COMPAT.md 与 docs/features.toml 中的 claude-settings-import 条目。"
},
"chrome": {
"navDocs": "文档",
"navStart": "指引",
@@ -6,6 +152,7 @@
"navFaq": "常见问题",
"navCommunity": "社区",
"navContribute": "贡献",
"navFeatures": "功能",
"navProduct": "产品",
"navModels": "模型",
"navPlugins": "插件",
@@ -46,10 +193,10 @@
"partialBadge": "(部分)"
},
"home": {
"metaTitle": "Codewhale:用自己的模型和工具,把想法做出来",
"metaDescription": "用 Codewhale 构建应用、自动处理工作,并连接你常用的工具。开源,支持你已有的模型 API、本地模型和自托管推理服务。",
"metaTitle": "Codewhale:开源编程智能体",
"metaDescription": "Codewhale 是终端里的开源编程智能体。用你选择的托管模型或本地模型读取、修改和测试项目。",
"heroTitle": "构建应用,让你的工作自动运行。",
"heroIntro": "{brand} 是一个开源智能体,可以编写代码、运行命令,并使用你连接的工具。你可以使用已有的模型 API,也可以在本地或自己的服务器上运行模型。",
"heroIntro": "{brand} 是终端里的开源编程智能体,可以读取文件、编写代码并运行命令。连接已有的模型 API 或本地模型,并选择哪些操作需要批准。",
"getCodewhale": "安装 Codewhale",
"heroInstallAria": "安装命令",
"exploreProduct": "探索 Codewhale",
@@ -874,14 +1021,14 @@
"title": "把 Codewhale 作为 MCP 服务器运行",
"blocks": [
{
"p": "其他 MCP 客户端——包括另一个 Codewhale 会话——都可以使用 Codewhale 的工具。只需注册一次:"
"p": "其他 MCP 客户端可以把 Codewhale 作为工具服务器。默认仅暴露只读的 `file_read` 和 `search` 工具。"
},
{
"code": "codewhale mcp add-self\ncodewhale mcp tools codewhale",
"lang": "终端"
},
{
"p": "`add-self` 会写入一条通过 stdio 运行 `codewhale serve --mcp` 的配置。每个客户端各自启动一个进程,不会打开任何网络端口。`codewhale serve --http` 则是另一回事——它是供应用使用的 [Runtime API](/docs/runtime-api)。"
"p": "`add-self` 注册通过 stdio 运行的 `codewhale serve --mcp`;`codewhale mcp-server` 是等价入口。除非操作者在服务器配置中明确允许,否则不会提供写入工具。[Runtime API](/docs/runtime-api) HTTP 是单独的传输方式。"
}
]
},
@@ -1190,6 +1337,25 @@
"title": "限制命令的访问范围",
"lede": "批准一条命令,决定的是它能不能运行;沙箱决定的是它运行之后能碰到什么。只要操作系统提供沙箱,Codewhale 就会使用它;没有沙箱时,也会如实告诉你。",
"sections": [
{
"id": "execution-policy",
"title": "检查执行策略规则",
"blocks": [
{
"code": "/permissions",
"lang": "Codewhale"
},
{
"p": "类型化权限依次按 User、Agent、BuiltinDefault 选择规则。同一来源层中,deny 优先于 ask 与 allow;匹配精度用于打破同级平局。"
},
{
"p": "硬性拒绝的命令前缀不能被类型化 allow 覆盖。allow 不会移除后续安全检查、仓库限制或沙箱边界。"
},
{
"p": "[阅读授权顺序与匹配规则](https://github.com/codewhale-hq/CodeWhale/blob/main/docs/AUTHORIZATION_ORDER.md)"
}
]
},
{
"id": "platforms",
"title": "查看你的平台提供了什么",
@@ -1759,6 +1925,25 @@
"title": "了解哪些数据会离开本机",
"lede": "Codewhale 在你的电脑上运行,只与你选择的模型提供商通信。这一页按目前的实际实现,列出数据分别去了哪里、匿名用量统计包含什么,以及如何关闭它。",
"sections": [
{
"id": "preview-request",
"title": "发送前查看请求",
"blocks": [
{
"p": "/preview-request 展示下一个主智能体回合的脱敏清单。这是供人使用的命令,不会发送请求,也不会写入对话或 Work 状态。"
},
{
"code": "/preview-request\n/preview-request json\n/preview-request json --prompt explain this project",
"lang": "Codewhale"
},
{
"note": "未提供 --prompt 时,路由和请求体不可用。已配置的分类器、钩子或待处理运行状态也可能阻止精确预览;清单会说明原因。"
},
{
"p": "[阅读请求预览约定](https://github.com/codewhale-hq/CodeWhale/blob/main/docs/PREVIEW_REQUEST.md)"
}
]
},
{
"id": "boundaries",
"title": "你的工作内容去了哪里",
@@ -1926,8 +2111,8 @@
"emptyBody": "构建时没有找到可解析的 CHANGELOG.md。GitHub 的发布列表仍然是权威记录。"
},
"computer-use": {
"metaTitle": "Mac 版 Computer Use · Codewhale",
"metaDescription": "下载并设置 Mac 版 Codewhale Computer Use。提供应用后台操作、权限设置,以及由用户控制的暂停和停止功能。",
"metaTitle": "Computer Use · 预览 · Codewhale",
"metaDescription": "预览功能:下载并设置 Mac 版 Codewhale Computer Use。提供应用后台操作、权限设置,以及由用户控制的暂停和停止功能。",
"title": "Computer Use",
"lead": "让 Codewhale 在应用中完成操作,你也可以继续工作。Mac 助手将权限设置、应用后台操作,以及暂停或停止输入的控制集中在菜单栏中。",
"publisher": "由 Codewhale 开发",
+17
View File
@@ -0,0 +1,17 @@
import generated from "@/data/agent-docs.generated.json";
import { DOC_TOPICS } from "./docs-map";
import { REPO_URL } from "./i18n/links";
export const AGENT_DOCS = generated;
export function buildTopicMarkdown(slug: string): string | null {
const document = AGENT_DOCS.find((entry) => entry.slug === slug);
const topic = DOC_TOPICS.find((entry) => entry.slug === slug);
if (!document || !topic) return null;
return [`# ${topic.label.en}`, "", topic.description.en, "", ...document.sources.flatMap((source) => [
`Source: ${REPO_URL}/blob/main/${source.path}`,
`SHA-256: ${source.sha256}`, "",
source.path.split("#", 1)[0].endsWith(".json") ? `\`\`\`json\n${source.content}\n\`\`\`` : source.content,
"",
])].join("\n");
}
+11
View File
@@ -0,0 +1,11 @@
export const AUTO_ROUTING_COPY = {
question: { en: "How does automatic model routing work?", zh: "模型自动路由如何工作?" },
answer: {
en: "With /model auto, each turn uses your declared default model unless you configure [auto.router] or enable [auto] cost_saving. No default classifier runs, and holding a DeepSeek key does not select one. /router (also /model router) offers Jev, Fast, Off and Custom presets. A configured classifier needs its provider credentials; unavailable or failed routing falls back to the declared default or the enabled fast sibling. Check the route in the Turn Inspector with Ctrl+Alt+O or /turn inspect.",
zh: "使用 /model auto 时,每个回合采用你声明的默认模型,除非你配置了 [auto.router] 或启用了 [auto] cost_saving。默认不会调用分类器,拥有 DeepSeek 密钥也不会自动选定一个。/router(也可用 /model router)提供 Jev、Fast、Off 和 Custom 预设。已配置的分类器需要相应提供商凭据;路由不可用或失败时,会回退到声明的默认模型或已启用的快速同系列模型。用 Ctrl+Alt+O 或 /turn inspect 在回合检查器中查看实际路由。",
},
cache: {
en: "Each turn sends the context it needs, including project instructions and tool definitions. Cache behavior depends on the provider, model and stable prompt prefix. Choose a smaller model explicitly when suitable; automatic routing changes models only through the settings you choose. Check /turn inspect for the route, tokens and reported cost.",
zh: "每个回合会发送所需上下文,包括项目说明和工具定义。缓存行为取决于提供商、模型和稳定的提示前缀。适合时请明确选择较小的模型;自动路由仅按你选择的设置切换模型。用 /turn inspect 查看实际路由、token 与报告的费用。",
},
};
+2 -2
View File
@@ -12,8 +12,8 @@ export const INSTALL_COMMANDS = {
export const INSTALL_COPY = {
windowsNote: { en: "Windows x64. Winget updates can lag behind GitHub releases; npm is another option.", zh: "适用于 Windows x64。Winget 更新可能晚于 GitHub 发布;也可以通过 npm 安装。" },
cargoNote: { en: "Builds from source. Requires current stable Rust and build tools. The Cargo package can lag behind GitHub releases.", zh: "从源码构建,需要当前稳定版 Rust 和构建工具。Cargo 包可能晚于 GitHub 发布。" },
metaTitle: { en: "Install · Codewhale", zh: "安装 · Codewhale" },
metaDescription: { en: "Install Codewhale on macOS, Linux, or Windows, connect a model, and run your first task. Covers package managers and source builds.", zh: "在 macOS、Linux 或 Windows 上安装 Codewhale,连接模型并运行第一项任务。也介绍包管理器和源码构建。" },
metaTitle: { en: "Install Codewhale, the terminal coding agent", zh: "安装终端编程智能体 Codewhale" },
metaDescription: { en: "Install the open-source terminal coding agent on macOS, Linux or Windows. Connect your model and run a task.", zh: "在 macOS、Linux 或 Windows 上安装开源终端编程智能体。连接你选择的模型并运行任务。" },
source: { en: "Read the verified guide on GitHub", zh: "查看 GitHub 上已验证的指南" },
translationNotice: { en: "Installation receipts retain the version actually tested; latest resolves to the published release.", zh: "本页采用经审阅的简体中文指南。安装回执保留实际测试版本;latest 以已发布版本为准。" },
configuration: { en: "Settings and configuration", zh: "设置与配置" },
+2 -2
View File
@@ -1,8 +1,8 @@
import type { LocalizedText } from "./vocabulary";
export const MODELS_COPY = {
metaTitle: { en: "Models and providers · Codewhale", zh: "模型与提供商 · Codewhale" },
metaDescription: { en: "Connect a hosted provider, a gateway, or a local model server, and switch models per session.", zh: "连接托管提供商、网关或本地模型服务,并按会话切换模型。" },
metaTitle: { en: "DeepSeek, Ollama and local models · Codewhale", zh: "DeepSeek、Ollama 与本地模型 · Codewhale" },
metaDescription: { en: "Use Codewhale with DeepSeek, Ollama, other hosted providers or local models. Configure credentials and endpoints, then choose a model per session.", zh: "让 Codewhale 使用 DeepSeek、Ollama、其他托管提供商或本地模型。配置凭据与端点,再按会话选择模型。" },
kicker: { en: "Models and providers", zh: "模型与提供商" },
title: { en: "Pick the right model for each task.", zh: "为每项任务选择合适的模型。" },
lead: { en: "Use a hosted model, a local server, or a gateway. Switch the provider or model whenever the work changes.", zh: "使用托管模型、本地服务或网关。工作变化时,随时切换提供商或模型。" },
+3 -3
View File
@@ -15,11 +15,11 @@ export const PLUGINS_COPY = {
marketplaceCta: { en: "Browse the Codewhale catalog", zh: "浏览 Codewhale 目录" },
docsCta: { en: "Plugin authoring guide", zh: "插件编写指南" },
cuLabel: { en: "First-party plugin · macOS beta", zh: "官方插件 · macOS Beta" },
cuLabel: { en: "First-party plugin · macOS preview", zh: "官方插件 · macOS 预览" },
cuTitle: { en: "Control apps with Computer Use", zh: "使用 Computer Use 操作应用" },
cuLead: {
en: "The agent observes the apps you choose, reads their controls through the accessibility tree, types and clicks, and records each action in a receipt. macOS is the qualified beta platform; Windows, Linux and HarmonyOS backends remain experimental and source-only.",
zh: "代理观察你选择的应用,通过无障碍树读取控件,执行输入与点击,并在回执中记录每一步操作。macOS 是完成认证的 Beta 平台;Windows、Linux 与 HarmonyOS 后端仍为实验性、仅提供源码。",
en: "Computer Use is a preview. The agent reads app controls, types and clicks, and records actions; Windows, Linux and HarmonyOS backends remain experimental and source-only.",
zh: "Computer Use 是预览功能。智能体读取应用控件、输入与点击,并记录操作;Windows、Linux 与 HarmonyOS 后端仍为实验性、仅提供源码。",
},
cuInstall: { en: "/plugin marketplace install codewhale computer-use", zh: "/plugin marketplace install codewhale computer-use" },
cuFeatures: [
+2 -2
View File
@@ -42,8 +42,8 @@ export const PRODUCT_COPY = {
zh: "构建应用,自动化工作流",
},
lede: {
en: "Codewhale is an open-source agent that writes code, runs commands and works with the tools you connect. Use your existing model APIs, or run models locally and on your own servers.",
zh: "Codewhale 是一个开源智能体,可以编写代码、运行命令,并使用你连接的工具。使用已有的模型 API,或在本地和自己的服务器上运行模型。",
en: "Codewhale is an open-source coding agent that reads files, writes code and runs commands in your terminal. Connect a hosted or local model and choose which actions need approval.",
zh: "Codewhale 是终端里的开源编程智能体,可以读取文件、编写代码并运行命令。连接托管模型或本地模型,并选择哪些操作需要批准。",
},
gainHeading: { en: "What you can build and automate", zh: "可以构建与自动化的工作" },
+120
View File
@@ -0,0 +1,120 @@
import type { IconName } from "@/components/icon";
import { REPO_URL } from "@/lib/i18n/links";
export const REPO_BLOB_BASE = `${REPO_URL}/blob/main`;
interface Integration {
name: string;
icon: IconName;
experimental?: boolean;
desc: { en: string; zh: string };
href: string;
}
export const INTEGRATIONS: Integration[] = [
{
name: "HTTP / SSE Runtime API",
icon: "terminal",
desc: {
en: "Full local HTTP + Server-Sent Events runtime API on 127.0.0.1:7878. Create threads, stream turns, manage background jobs, and control approval decisions — all from any HTTP client or the bundled mobile page.",
zh: "完整的本地 HTTP + Server-Sent Events Runtime API,监听 127.0.0.1:7878。创建线程、流式对话、管理后台任务、控制审批决策——任意 HTTP 客户端或内置手机页面皆可调用。",
},
href: `${REPO_BLOB_BASE}/docs/RUNTIME_API.md`,
},
{
name: "ACP (Agent Client Protocol)",
icon: "plug",
desc: {
en: "ACP stdio connects compatible editors to the existing Engine. It supports durable session creation, listing, loading, prompts, cancellation and model selection. Its local profile admits file/search/git/patch and foreground shell only with editor support and operator permission; MCP, dynamic tools and background jobs are unavailable.",
zh: "ACP stdio 将兼容编辑器连接到现有 Engine,支持持久会话创建、列举、加载、提示、取消与模型选择。本地配置允许文件、搜索、git 和补丁;前台 shell 还需编辑器支持与操作者许可;MCP、动态工具与后台任务不可用。",
},
href: `${REPO_BLOB_BASE}/docs/RUNTIME_API.md`,
},
{
name: "MCP (Model Context Protocol)",
icon: "plug",
desc: {
en: "Connect Codewhale to external tools and services through configured MCP servers over stdio or HTTP/SSE, or expose read-only file_read and search to another MCP client by default.",
zh: "通过已配置的 MCP 服务器(stdio 或 HTTP/SSE)将 Codewhale 连接到外部工具和服务,或默认向其他 MCP 客户端提供只读 file_read 与 search。",
},
href: `${REPO_BLOB_BASE}/docs/MCP.md`,
},
{
name: "VS Code Extension",
icon: "monitor",
desc: {
en: "Early companion for the local runtime. It can open Codewhale in a terminal, start and check the Runtime API, and show read-only thread summaries and restore points. It does not yet provide full chat, inline edits, or editor actions.",
zh: "本地 Runtime 的早期配套扩展。它可以在终端中打开 Codewhale、启动并检查 Runtime API,以及显示只读线程摘要和还原点;目前尚不提供完整聊天、内联编辑或编辑器操作。",
},
href: "https://github.com/codewhale-hq/CodeWhale/tree/main/extensions/vscode",
},
{
name: "CodeWhale GUI (VS Code)",
icon: "monitor",
desc: {
en: "The community-maintained graphical frontend, in a separate repository: chat, threads, live file changes, and task tracking in a VS Code sidebar over this Runtime API. Install it from the VS Code Marketplace; the source is on GitHub.",
zh: "社区维护的图形前端,位于独立仓库:在 VS Code 侧边栏中基于此 Runtime API 进行对话、管理线程、查看实时文件变更与任务进度。可从 VS Code Marketplace 安装;源码见 GitHub。",
},
href: "https://marketplace.visualstudio.com/items?itemName=HengQuWorld.brotherwhale-vscode",
},
{
name: "Telegram Bridge",
icon: "message",
desc: {
en: "First-party Telegram bot bridge. Start a headless Codewhale session, then chat with it from any Telegram client — approvals, tool results, and completions surface inline.",
zh: "官方 Telegram 机器人桥接。启动无头 Codewhale 会话,在任何 Telegram 客户端中与之对话——审批、工具结果和完成状态内联展示。",
},
href: "https://github.com/codewhale-hq/CodeWhale/tree/main/integrations/telegram-bridge",
},
{
name: "Feishu / Lark Bridge",
icon: "message",
desc: {
en: "First-party Feishu / Lark bot bridge. Chat-native agent loop inside your Feishu workspace with approval messages, session linking, and audit trail.",
zh: "官方飞书 / Lark 机器人桥接。在飞书工作区内实现聊天原生 Agent 循环,支持审批消息、会话关联和审计日志。",
},
href: "https://github.com/codewhale-hq/CodeWhale/tree/main/integrations/feishu-bridge",
},
{
name: "Weixin Bridge",
icon: "message",
experimental: true,
desc: {
en: "Experimental Weixin / WeChat bridge. Receive agent completions and approvals inside WeChat; early-stage and not recommended for production deployments.",
zh: "实验性微信桥接。在微信中接收 Agent 完成通知和审批;早期阶段,不建议用于生产环境。",
},
href: "https://github.com/codewhale-hq/CodeWhale/tree/main/integrations/weixin-bridge",
},
];
export const TRUST = [
{
title: { en: "Runs on your machine", zh: "本机运行" },
body: {
en: "The Runtime API binds 127.0.0.1 by default. The local runtime does not require a Codewhale account or hosted relay.",
zh: "Runtime API 默认仅监听 127.0.0.1。本地运行时不需要 Codewhale 账户或托管中继。",
},
},
{
title: { en: "Auth required", zh: "认证必需" },
body: {
en: "Runtime API routes (/v1/*) require a Bearer token. Pass --auth-token at startup or set CODEWHALE_RUNTIME_TOKEN. Only a loopback bind can turn this off, with --insecure-no-auth.",
zh: "Runtime API 路由(/v1/*)需要 Bearer Token。启动时传入 --auth-token,或设置 CODEWHALE_RUNTIME_TOKEN 环境变量。仅在回环地址上可用 --insecure-no-auth 关闭认证。",
},
},
{
title: { en: "Permissions user-controlled", zh: "权限用户控制" },
body: {
en: "Remote clients submit requests and approval decisions through the authenticated Runtime API. Local mode, permission posture, and sandbox policy still apply.",
zh: "远程客户端通过经过认证的 Runtime API 提交请求与审批决定。本地模式、权限姿态和沙箱策略仍然生效。",
},
},
{
title: { en: "Open protocols", zh: "开放协议" },
body: {
en: "The HTTP/SSE Runtime API, MCP surface, and ACP stdio transport serve different integration needs; choose the interface your compatible client supports.",
zh: "HTTP/SSE Runtime API、MCP 和ACP stdio 传输分别服务于不同集成场景;请根据客户端需要选择对应接口。",
},
},
];
+6
View File
@@ -23,6 +23,9 @@ export const TOOLS_COPY = {
{ name: "MCP", detail: { en: "mcp_<server>_<tool> — registered from ~/.codewhale/mcp.json.", zh: "mcp_<server>_<tool>——从 ~/.codewhale/mcp.json 注册。" } },
],
compatibilityTitle: { en: "Replay compatibility", zh: "回放兼容" },
lspTitle: { en: "Read language-server diagnostics", zh: "读取语言服务器诊断" },
lspBody: { en: "After file edits, LSP diagnostics can report errors to the agent. Add a custom server by file extension under [lsp.custom]; install the server executable separately.", zh: "文件修改后,LSP 诊断可向智能体报告错误。通过 [lsp.custom] 按扩展名添加自定义服务器;服务器可执行文件需要单独安装。" },
lspDocs: { en: "PHP and custom LSP server setup", zh: "PHP 与自定义 LSP 服务器设置" },
compatibility: { en: "Legacy names remain only for saved transcripts and protocol clients. Exact old calls retain their handlers but stay out of new catalogs and tool_search. Unknown names are never guessed or rewritten.", zh: "旧名称仅为已保存的记录与协议客户端保留。精确旧调用仍使用原处理器,但不会出现在新目录或 tool_search 中。未知名称不会被猜测或改写。" },
} satisfies {
metaTitle: LocalizedText;
@@ -32,5 +35,8 @@ export const TOOLS_COPY = {
reference: LocalizedText;
rows: { name: string; detail: LocalizedText }[];
compatibilityTitle: LocalizedText;
lspTitle: LocalizedText;
lspBody: LocalizedText;
lspDocs: LocalizedText;
compatibility: LocalizedText;
};
+5 -6
View File
@@ -92,13 +92,12 @@ describe("sitemap and hreflang preservation", () => {
});
it("keeps sitemap and hreflang output aligned with real translation coverage", () => {
// 18 home locales + 18 /computer-use locales + English-only install + (en, zh) for every
// other route (including /docs/guide, /product, /plugins, and /changelog, whose bodies
// ship en/zh only).
// Home and Computer Use have 18 locales; install and the source catalogue are English.
// Other page bodies ship English and Chinese.
const existingEntries = sitemapEntries.filter(
(entry) => new URL(entry.url).pathname.split("/")[2] !== "ratatui",
);
expect(existingEntries).toHaveLength(109);
expect(existingEntries).toHaveLength(114);
expect(sitemapEntries.filter(entry => entry.url.endsWith("/install")).map(entry => entry.url))
.toEqual([`${SITE_URL}/en/install`]);
expect(sitemapEntries.some(entry => entry.url.endsWith("/pricing"))).toBe(false);
@@ -139,7 +138,7 @@ describe("sitemap and hreflang preservation", () => {
expect(entries.map((entry) => entry.url)).toEqual(expectedUrls);
expect(new Set(sitemapEntries.map((entry) => entry.url)).size).toBe(sitemapEntries.length);
for (const entry of entries) {
expect(Object.keys(entry.alternates?.languages ?? {})).toEqual(["en", "zh"]);
expect(Object.keys(entry.alternates?.languages ?? {})).toEqual(entry.url.endsWith("/ratatui") ? ["en", "zh"] : ["en"]);
}
});
@@ -217,7 +216,7 @@ describe("navigation parity and accessibility", () => {
const reference = buildNavLinks("en", getChrome("en")).map((l) =>
l.href.replace(/^\/en\//, ""),
);
expect(reference).toEqual(["product", "models", "plugins", "docs"]);
expect(reference).toEqual(["product", "features", "models", "plugins", "docs"]);
const moreReference = buildSecondaryNavLinks("en", getChrome("en")).map((l) =>
l.href.replace(/^\/en\//, ""),
);
+17 -5
View File
@@ -182,7 +182,7 @@ export const DOC_TOPICS: DocTopic[] = [
en: "The OS sandbox on macOS, Linux, and Windows, how to turn it on, and how much a command may write.",
zh: "macOS、Linux 和 Windows 上的操作系统沙箱、如何开启,以及命令能写到哪里。",
},
repoSource: "docs/SANDBOX.md",
repoSource: ["docs/SANDBOX.md", "docs/AUTHORIZATION_ORDER.md"],
hasPage: true,
category: "core-concepts",
},
@@ -194,7 +194,7 @@ export const DOC_TOPICS: DocTopic[] = [
en: "What stays local, what a provider receives, what usage counting sends, and how to turn it off.",
zh: "哪些留在本地、提供商会收到什么、用量统计发送什么,以及如何关闭。",
},
repoSource: ["docs/SANDBOX.md", "docs/AUTHORIZATION_ORDER.md", "docs/TELEMETRY.md", "docs/public-surface-facts.json"],
repoSource: ["docs/SANDBOX.md", "docs/AUTHORIZATION_ORDER.md", "docs/TELEMETRY.md", "docs/public-surface-facts.json", "docs/PREVIEW_REQUEST.md"],
hasPage: true,
category: "core-concepts",
},
@@ -230,10 +230,22 @@ export const DOC_TOPICS: DocTopic[] = [
en: "Install, find, trust, and load reusable instruction packages.",
zh: "安装、查找、信任并加载可复用的指令包。",
},
repoSource: "docs/SKILLS.md",
hasPage: false,
repoSource: ["docs/SKILLS.md", "docs/CLAUDE_PLUGIN_COMPAT.md"],
hasPage: true,
category: "extending",
},
{
id: "claude-code",
slug: "claude-code",
label: { en: "Move from Claude Code", zh: "从 Claude Code 迁移" },
description: {
en: "Keep compatible instructions and skills, and review settings and MCP imports without running Claude Code plugin runtimes.",
zh: "保留兼容的指令与技能,审阅设置与 MCP 导入;不会运行 Claude Code 插件运行时。",
},
repoSource: ["docs/CLAUDE_PLUGIN_COMPAT.md", "docs/CONFIGURATION.md"],
hasPage: true,
category: "getting-started",
},
{
id: "plugins",
slug: "plugins",
@@ -346,7 +358,7 @@ export const DOC_TOPICS: DocTopic[] = [
en: "The small set of tools every session starts with, and how Codewhale finds the rest.",
zh: "每个会话默认携带的少量工具,以及 Codewhale 如何按需找到其余工具。",
},
repoSource: ["docs/TOOL_SURFACE.md", "docs/RUNTIME_SIMPLIFICATION_DESIGN.md"],
repoSource: ["docs/TOOL_SURFACE.md", "docs/RUNTIME_SIMPLIFICATION_DESIGN.md", "docs/LSP_PHP_CUSTOM.md"],
hasPage: true,
category: "reference",
},
+90 -4
View File
@@ -30,6 +30,92 @@ export interface DocTask {
}
export const DOC_TASKS: DocTask[] = [
{
"id": "preview-request",
"label": {
"en": "Inspect the outbound request",
"zh": "检查出站请求"
},
"description": {
"en": "Read a redacted request manifest without sending or changing session state.",
"zh": "读取脱敏请求清单,不发送请求也不修改会话状态。"
},
"href": "/docs/trust",
"topicId": "trust",
"keywords": {
"en": "preview-request preview_request dryrun prompt payload manifest offline",
"zh": "请求 提示 预览 清单 离线"
}
},
{
"id": "language-server",
"label": {
"en": "Read language-server diagnostics",
"zh": "读取语言服务器诊断"
},
"description": {
"en": "Return LSP errors after edits and configure custom servers by file extension.",
"zh": "修改后返回 LSP 错误,并按文件扩展名配置自定义服务器。"
},
"href": "/docs/tools",
"topicId": "tools",
"keywords": {
"en": "lsp diagnostics type errors language server php custom",
"zh": "语言服务器 诊断 类型 错误"
}
},
{
"id": "execution-policy",
"label": {
"en": "Inspect execution policy rules",
"zh": "检查执行策略规则"
},
"description": {
"en": "Read rule sources, matchers and scope; understand allow, ask and deny precedence.",
"zh": "查看规则来源、匹配器与作用域,了解 allow、ask 和 deny 的优先级。"
},
"href": "/docs/sandbox",
"topicId": "sandbox",
"keywords": {
"en": "exec-policy execpolicy permissions rules prefix deny ask allow",
"zh": "执行策略 权限 规则 拒绝 审批"
}
},
{
"id": "manage-skills",
"label": {
"en": "Manage reusable skills",
"zh": "管理可复用技能"
},
"description": {
"en": "Find SKILL.md folders, import into owned roots and control invocation.",
"zh": "查找 SKILL.md 文件夹、导入自有目录并控制调用。"
},
"href": "/docs/skills",
"topicId": "skills",
"keywords": {
"en": "skills trust skill.md invocation install claude agents",
"zh": "技能 信任 安装 调用"
}
},
{
"id": "move-from-claude-code",
"label": {
"en": "Move from Claude Code",
"zh": "从 Claude Code 迁移"
},
"description": {
"en": "Keep compatible instructions and skills, and review a settings import plan.",
"zh": "保留兼容指令与技能,并审阅设置导入方案。"
},
"href": "/docs/claude-code",
"topicId": "claude-code",
"keywords": {
"en": "claude code alternative import-claude plugin settings migration",
"zh": "Claude Code 替代 迁移 导入 插件 设置"
}
},
{
id: "install",
label: { en: "Install Codewhale", zh: "安装 Codewhale" },
@@ -98,14 +184,14 @@ export const DOC_TASKS: DocTask[] = [
},
{
id: "receipts",
label: { en: "Keep a receipt of a review", zh: "为审查保留收据" },
label: { en: "See what a session did", zh: "查看会话做了什么" },
description: {
en: "Write a review receipt and check it before you push.",
zh: "生成审查收据,并在推送前核对它。",
en: "Read a session receipt of commands, file changes, tools and approval decisions.",
zh: "阅读会话收据,查看命令、文件修改、工具与审批决策。",
},
href: "/docs/review",
topicId: "review",
keywords: { en: "receipt write-receipt check-receipt pre-push export", zh: "收据 推送 导出" },
keywords: { en: "receipt receipts audit tool approval command file export", zh: "收据 推送 导出" },
},
{
id: "watch-sessions",
+2
View File
@@ -1,3 +1,4 @@
import { AUTO_ROUTING_COPY } from "./content/faq-routing";
import { createElement } from "react";
import { readFileSync } from "node:fs";
import { describe, expect, it } from "vitest";
@@ -60,6 +61,7 @@ describe("FAQPage structured data", () => {
it("covers all 42 curated pairs from the FAQ page arrays", () => {
const questions = [...faqPage.matchAll(/^\s+q: "(.+)"/gm)].map((match) => match[1]);
questions.push(AUTO_ROUTING_COPY.question.en, AUTO_ROUTING_COPY.question.zh);
expect(questions).toHaveLength(42);
expect(new Set(questions).size).toBe(42);
expect(faqPage).toContain("const faqEn");
+41
View File
@@ -0,0 +1,41 @@
import generated from "@/data/features.generated.json";
import { REPO_URL } from "./i18n/links";
export type FeatureStatus = "stable" | "flagged" | "experimental";
export type SurfaceStatus = "stable" | "partial" | "preview" | "none";
export interface Feature {
id: string;
name: string;
summary: string;
status: FeatureStatus;
surfaces: Partial<Record<"tui" | "api" | "web", SurfaceStatus>>;
since: string | null;
flag: string | null;
docs: string | null;
registryLine: number;
}
export const FEATURE_CATALOGUE = generated as {
format: string;
source: { path: string; sha256: string };
features: Feature[];
};
export function featureDocsHref(feature: Feature): string {
return `${REPO_URL}/blob/main/${feature.docs ?? `docs/features.toml#L${feature.registryLine}`}`;
}
export function publishedFeatureNames(version: string): string[] {
const parts = (value: string) => /^\d+\.\d+\.\d+$/.test(value) ? value.split(".").map(Number) : null;
const release = parts(version);
if (!release) return [];
return FEATURE_CATALOGUE.features.filter((feature) => {
if (feature.status !== "stable" || !feature.since) return false;
const since = parts(feature.since);
if (!since) return false;
for (let i = 0; i < 3; i++) {
if (since[i] !== release[i]) return since[i] < release[i];
}
return true;
}).map((feature) => feature.name);
}
+4 -1
View File
@@ -13,6 +13,7 @@ import { hasComputerUseTranslation } from "./dictionaries";
const ROUTE_CONTENT_LOCALES: Readonly<Record<string, readonly string[]>> = {
"/": locales,
"/install": ["en"],
"/features": ["en"],
"/computer-use": locales.filter(hasComputerUseTranslation),
};
@@ -26,7 +27,9 @@ function normalizedPath(path: string): string {
/** Locales with a genuine page-body translation for an indexable route. */
export function contentLocalesForPath(path: string): readonly string[] {
return ROUTE_CONTENT_LOCALES[normalizedPath(path)] ?? DEFAULT_CONTENT_LOCALES;
const normalized = normalizedPath(path);
if (normalized.startsWith("/ratatui/")) return ["en"];
return ROUTE_CONTENT_LOCALES[normalized] ?? DEFAULT_CONTENT_LOCALES;
}
/**
+1
View File
@@ -20,6 +20,7 @@ export const chrome: ChromeDict = {
navCommunity: "المجتمع",
navContribute: "المساهمة",
navFeatures: "القدرات",
navProduct: "المنتج",
navModels: "النماذج",
navPlugins: "الإضافات",
+1 -1
View File
@@ -7,7 +7,7 @@ import type { ComputerUseDict } from "../types";
* as the app shows them; the macOS names use the Arabic system UI labels.
*/
export const computerUse: ComputerUseDict = {
metaTitle: "Computer Use لنظام Mac · Codewhale",
metaTitle: "Computer Use · معاينة · Codewhale",
metaDescription: "نزّل Codewhale Computer Use لنظام Mac وجهّزه. تحكّم في التطبيقات في الخلفية، وإعداد الأذونات، وأزرار Pause وStop بيدك.",
title: "Computer Use",
lead: "دع Codewhale يعمل داخل تطبيقاتك بينما تواصل عملك. يجمع مساعد Mac في شريط القوائم الأذونات والتحكم في التطبيقات في الخلفية وإمكانية إيقاف الإدخال مؤقتًا أو إنهائه.",
+16
View File
@@ -0,0 +1,16 @@
import type { FeaturesDict } from "../types";
export const features: FeaturesDict = {
title: "اطّلع على قدرات Codewhale",
description: "تصفّح أوامر Codewhale وأدواته وقدرات Runtime مع حالة التوفّر والوثائق.",
notice: "يشمل هذا الدليل {count} مدخلاً من المصدر v{version}. الأسماء والأوصاف بالإنجليزية؛ تحقّق من النسخة المثبّتة.",
stable: "مستقر",
flagged: "يتطلب علامة",
experimental: "تجريبي",
partial: "جزئي",
preview: "معاينة",
none: "غير متاح",
docs: "اقرأ الوثائق",
source: "اقرأ مدخل المصدر",
exportJson: "نزّل ملف JSON للقدرات",
};
+3 -5
View File
@@ -3,12 +3,10 @@ import type { HomeDict } from "../types";
/** Arabic home copy: useful work with chosen models and connected tools. */
export const home: HomeDict = {
metaTitle: "Codewhale: ابنِ باستخدام نماذجك وأدواتك",
metaDescription:
"ابنِ تطبيقات وأتمت العمل واستخدم الأدوات المتصلة مع Codewhale. مفتوح المصدر، مع واجهات نماذجك أو الاستدلال المحلي والمستضاف على أجهزتك.",
metaTitle: "Codewhale: وكيل برمجة مفتوح المصدر",
metaDescription: "Codewhale وكيل برمجة مفتوح المصدر للطرفية. اقرأ المشاريع وعدّلها واختبرها باستخدام نماذجك المستضافة أو المحلية.",
heroTitle: "أنشئ تطبيقات وأتمت عملك.",
heroIntro:
"{brand} وكيل مفتوح المصدر يكتب التعليمات البرمجية وينفذ الأوامر ويعمل مع الأدوات التي تربطها. استخدم واجهات API للنماذج التي تستخدمها بالفعل، أو شغّل النماذج محليًا وعلى خوادمك الخاصة.",
heroIntro: "{brand} وكيل برمجة مفتوح المصدر يقرأ الملفات ويكتب الشيفرة وينفّذ الأوامر في الطرفية. اربط واجهة API لنموذجك أو نموذجاً محلياً واختر الإجراءات التي تتطلب موافقتك.",
getCodewhale: "ثبّت Codewhale",
heroInstallAria: "أمر التثبيت",
exploreProduct: "استكشف Codewhale",
+1
View File
@@ -25,6 +25,7 @@ export const chrome: ChromeDict = {
navCommunity: "Comunitat",
navContribute: "Col·laborar",
navFeatures: "Capacitats",
navProduct: "Producte",
navModels: "Models",
navPlugins: "Plugins",
+1 -1
View File
@@ -8,7 +8,7 @@ import type { ComputerUseDict } from "../types";
* the names the Catalan system UI shows.
*/
export const computerUse: ComputerUseDict = {
metaTitle: "Computer Use per a Mac · Codewhale",
metaTitle: "Computer Use · Previsualització · Codewhale",
metaDescription: "Baixa i configura Codewhale Computer Use per a Mac. Control d’aplicacions en segon pla, configuració de permisos i controls humans de Pause i Stop.",
title: "Computer Use",
lead: "Deixa que Codewhale treballi a les teves aplicacions mentre tu continues treballant. L’ajudant per a Mac posa els permisos, el control d’aplicacions en segon pla i una manera de pausar o aturar l’entrada a la barra de menús.",
+16
View File
@@ -0,0 +1,16 @@
import type { FeaturesDict } from "../types";
export const features: FeaturesDict = {
title: "Consulta les capacitats de Codewhale",
description: "Explora les ordres, eines i capacitats de Runtime de Codewhale, amb disponibilitat i documentació.",
notice: "El catàleg inclou {count} entrades del codi font v{version}. Els noms i les descripcions són en anglès; comprova la versió instal·lada.",
stable: "Estable",
flagged: "Requereix una opció",
experimental: "Experimental",
partial: "Parcial",
preview: "Previsualització",
none: "No disponible",
docs: "Llegir documentació",
source: "Veure entrada del codi",
exportJson: "Baixar JSON de capacitats",
};
+3 -5
View File
@@ -3,12 +3,10 @@ import type { HomeDict } from "../types";
/** Catalan home copy: useful work with chosen models and connected tools. */
export const home: HomeDict = {
metaTitle: "Codewhale: crea amb els teus models i eines",
metaDescription:
"Crea aplicacions, automatitza fluxos de treball i utilitza eines connectades amb Codewhale. Codi obert, amb les teves API de models o inferència local i autoallotjada.",
metaTitle: "Codewhale: agent de programació de codi obert",
metaDescription: "Codewhale és un agent de programació de codi obert per al terminal. Llegeix, edita i prova projectes amb els teus models allotjats o locals.",
heroTitle: "Crea aplicacions i automatitza la teva feina.",
heroIntro:
"{brand} és un agent de codi obert que escriu codi, executa ordres i treballa amb les eines que connectes. Fes servir les API de models que ja utilitzes o executa models localment i als teus propis servidors.",
heroIntro: "{brand} és un agent de programació de codi obert que llegeix fitxers, escriu codi i executa ordres al terminal. Connecta la teva API de models o un model local i tria quines accions necessiten aprovació.",
getCodewhale: "Instal·lar Codewhale",
heroInstallAria: "Ordre d'instal·lació",
exploreProduct: "Explora Codewhale",
+1
View File
@@ -25,6 +25,7 @@ export const chrome: ChromeDict = {
navCommunity: "Community",
navContribute: "Mitwirken",
navFeatures: "Funktionen",
navProduct: "Produkt",
navModels: "Modelle",
navPlugins: "Plugins",
+1 -1
View File
@@ -8,7 +8,7 @@ import type { ComputerUseDict } from "../types";
* the other German dictionaries: knapp, Anrede per Du.
*/
export const computerUse: ComputerUseDict = {
metaTitle: "Computer Use für den Mac · Codewhale",
metaTitle: "Computer Use · Vorschau · Codewhale",
metaDescription: "Codewhale Computer Use für den Mac herunterladen und einrichten. App-Steuerung im Hintergrund, Berechtigungen einrichten und Pause und Stop in deiner Hand.",
title: "Computer Use",
lead: "Lass Codewhale in deinen Apps arbeiten, während du weiterarbeitest. Der Mac-Helfer bringt Berechtigungen, App-Steuerung im Hintergrund und eine Möglichkeit, Eingaben zu pausieren oder zu stoppen, in deine Menüleiste.",
+16
View File
@@ -0,0 +1,16 @@
import type { FeaturesDict } from "../types";
export const features: FeaturesDict = {
title: "Prüfe die Funktionen von Codewhale",
description: "Entdecke Befehle, Werkzeuge und Runtime-Funktionen von Codewhale mit Verfügbarkeit und Dokumentation.",
notice: "Der Katalog enthält {count} Einträge aus Quellversion v{version}. Namen und Beschreibungen sind auf Englisch; prüfe deine installierte Version.",
stable: "Stabil",
flagged: "Schalter erforderlich",
experimental: "Experimentell",
partial: "Teilweise",
preview: "Vorschau",
none: "Nicht verfügbar",
docs: "Dokumentation lesen",
source: "Quelleintrag lesen",
exportJson: "Funktions-JSON herunterladen",
};
+3 -5
View File
@@ -3,12 +3,10 @@ import type { HomeDict } from "../types";
/** German home copy: useful work with chosen models and connected tools. */
export const home: HomeDict = {
metaTitle: "Codewhale: Bauen mit deinen Modellen und Werkzeugen",
metaDescription:
"Baue Apps, automatisiere Abläufe und arbeite mit verbundenen Werkzeugen. Codewhale ist Open Source und nutzt deine Modell-APIs oder lokale und selbst gehostete Inferenz.",
metaTitle: "Codewhale: ein Open-Source-Programmieragent",
metaDescription: "Codewhale ist ein Open-Source-Programmieragent für dein Terminal. Lies, bearbeite und teste Projekte mit deinen gehosteten oder lokalen Modellen.",
heroTitle: "Erstelle Apps und automatisiere deine Arbeit.",
heroIntro:
"{brand} ist ein Open-Source-Agent, der Code schreibt, Befehle ausführt und mit den Tools arbeitet, die du verbindest. Nutze deine vorhandenen Modell-APIs oder führe Modelle lokal und auf deinen eigenen Servern aus.",
heroIntro: "{brand} ist ein Open-Source-Programmieragent, der Dateien liest, Code schreibt und Befehle im Terminal ausführt. Verbinde deine Modell-API oder ein lokales Modell und wähle, welche Aktionen eine Zustimmung brauchen.",
getCodewhale: "Codewhale installieren",
heroInstallAria: "Installationsbefehl",
exploreProduct: "Codewhale entdecken",
+1
View File
@@ -12,6 +12,7 @@ export const chrome: ChromeDict = {
navCommunity: "Community",
navContribute: "Contribute",
navFeatures: "Capabilities",
navProduct: "Product",
navModels: "Models",
navPlugins: "Plugins",
+2 -2
View File
@@ -7,8 +7,8 @@ import type { ComputerUseDict } from "../types";
* macOS setting names stay as the app shows them.
*/
export const computerUse: ComputerUseDict = {
metaTitle: "Computer Use for Mac · Codewhale",
metaDescription: "Download and set up Codewhale Computer Use for Mac. Background app control, permission setup, and human Pause and Stop controls.",
metaTitle: "Computer Use · Preview · Codewhale",
metaDescription: "Preview: download and set up Codewhale Computer Use for Mac. Background app control, permission setup, and human Pause and Stop controls.",
title: "Computer Use",
lead: "Let Codewhale work in your apps while you keep working. The Mac helper brings permissions, background app control, and a way to pause or stop input to your menu bar.",
publisher: "By Codewhale",
@@ -0,0 +1,71 @@
import type { DocsPageDict } from "../types";
export const docsClaudeCode: DocsPageDict = {
metaTitle: "Move from Claude Code · Codewhale Docs",
metaDescription: "Use Codewhale as an open-source Claude Code alternative. Bring compatible instructions and skills, and review a settings and MCP import plan.",
bodyClassName: "text-ink-soft leading-relaxed",
title: "Move from Claude Code",
lede: "Keep compatible project instructions and skill folders while choosing your own model connection. Review settings and plugin imports before applying them.",
sections: [
{
"id": "instructions",
"title": "Keep your project instructions",
"blocks": [
{
"p": "AGENTS.md is the canonical project instruction file. CLAUDE.md and .claude/instructions.md are compatibility fallbacks; they do not override Codewhale security controls."
},
{
"p": "Plain .claude/skills/<name>/SKILL.md folders are discovered through the normal [skills registry](/docs/skills), with workspace trust and invocation controls."
}
]
},
{
"id": "settings",
"title": "Review a settings import",
"blocks": [
{
"code": "/import-claude",
"lang": "Codewhale"
},
{
"p": "The command reads Claude settings and writes a reviewable report and unapplied config bundle. MCP servers use the existing import consent flow; permissions and hooks need separate review."
},
{
"note": "Secret-shaped and unknown environment values are not imported or echoed. Running the plan does not enable servers or apply permissions."
}
]
},
{
"id": "plugins",
"title": "Install the supported plugin subset",
"blocks": [
{
"code": "/plugin install <spec>",
"lang": "Codewhale"
},
{
"p": "The declarative .claude-plugin/plugin.json subset supports skills, commands, agent profiles and MCP declarations. Codewhale review hashes and explicit trust and enablement still apply."
},
{
"note": "Codewhale does not run Claude Code plugin runtimes. Hooks, plugin LSP declarations, build steps and TypeScript agents are outside this importer."
},
{
"p": "[Read the compatibility limits](https://github.com/codewhale-hq/CodeWhale/blob/main/docs/CLAUDE_PLUGIN_COMPAT.md). Choose credentials and endpoints in [model setup](/models)."
}
]
}
],
next: [
{
"href": "/docs/skills",
"label": "Manage skills",
"note": "Inspect compatible directories before importing."
},
{
"href": "/docs/auth",
"label": "Connect a provider",
"note": "Use your chosen hosted or local model."
}
],
sourceNote: "Source: docs/CONFIGURATION.md, docs/CLAUDE_PLUGIN_COMPAT.md and the claude-settings-import entry in docs/features.toml."
};
+2 -2
View File
@@ -97,7 +97,7 @@ codewhale mcp add tracker --url "https://example.com/mcp" --bearer-token-env-var
title: "Run Codewhale as an MCP server",
blocks: [
{
p: "Other MCP clients — including another Codewhale session — can use Codewhale's tools. Register it once:",
p: "Other MCP clients can use Codewhale as a tool server. By default, it exposes only read-only `file_read` and `search` tools.",
},
{
code: `codewhale mcp add-self
@@ -105,7 +105,7 @@ codewhale mcp tools codewhale`,
lang: "Terminal",
},
{
p: "`add-self` writes an entry that runs `codewhale serve --mcp` over stdio. Each client starts its own process; no network port is opened. `codewhale serve --http` is a different thing — the [Runtime API](/docs/runtime-api) for apps.",
p: "`add-self` registers `codewhale serve --mcp` over stdio; `codewhale mcp-server` is the equivalent entry point. Write tools stay withheld unless the operator explicitly permits them in server configuration. [Runtime API](/docs/runtime-api) HTTP is a separate transport.",
},
],
},
+20 -4
View File
@@ -16,6 +16,25 @@ export const docsReview: DocsReviewDict = {
lede:
"Codewhale shows you each edit as it happens and keeps a snapshot of your workspace before and after every turn. Use this page to check what changed, put files back, and get a second opinion before you push.",
sections: [
{
"id": "receipts",
"title": "See what a session did",
"blocks": [
{
"p": "Session receipts list recorded file changes, commands, tools, agents, approvals and failures. Review receipts below cover a separate code review."
},
{
"code": "/receipts\n/receipts json\ncodewhale receipts --last --format md\nGET /v1/threads/{id}/receipt\nGET /v1/threads/{id}/turns/{turn_id}/receipt",
"lang": "Codewhale / Terminal / HTTP"
},
{
"p": "These surfaces only read records. They never call a provider, run tools or change session state."
},
{
"note": "A Runtime receipt does not itemize files changed by shell commands. The terminal can report changes from its turn snapshots; older records may omit who decided an approval."
}
]
},
{
id: "diff",
title: "See the changes",
@@ -76,7 +95,7 @@ codewhale review --pr 123 # a GitHub pull request (needs gh)`,
],
},
{
id: "receipts",
id: "review-receipts",
title: "Keep a receipt of the review",
blocks: [
{
@@ -94,9 +113,6 @@ codewhale review --base origin/main --check-receipt`,
"`--receipt-path <file>` writes or reads a specific receipt instead of the latest one.",
],
},
{
note: "Receipts cover code reviews today. A receipt for an ordinary agent turn — every tool call, approval, and file change in one export — is designed but not built yet.",
},
],
},
{
@@ -15,6 +15,25 @@ export const docsSandbox: DocsSandboxDict = {
lede:
"Approving a command decides whether it runs. A sandbox decides what it can reach once it does. Codewhale uses the operating system's sandbox where one is available and tells you plainly when there is none.",
sections: [
{
"id": "execution-policy",
"title": "Inspect execution policy rules",
"blocks": [
{
"code": "/permissions",
"lang": "Codewhale"
},
{
"p": "Typed permissions select User, Agent and BuiltinDefault rules in that order. Within one source layer, deny wins over ask and allow; specificity breaks ties."
},
{
"p": "Hard denied command prefixes cannot be overridden by a typed allow. An allow never removes later safety checks, repository restrictions or sandbox limits."
},
{
"p": "[Read the authorization order and matching rules](https://github.com/codewhale-hq/CodeWhale/blob/main/docs/AUTHORIZATION_ORDER.md)"
}
]
},
{
id: "platforms",
title: "Check what your platform provides",
@@ -0,0 +1,65 @@
import type { DocsPageDict } from "../types";
export const docsSkills: DocsPageDict = {
metaTitle: "Manage skills · Codewhale Docs",
metaDescription: "Find, install and trust SKILL.md instruction packages. Control user and model invocation and import compatible Claude Code skills.",
bodyClassName: "text-ink-soft leading-relaxed",
title: "Manage reusable skills",
lede: "Skills are SKILL.md instruction packages. Discover compatible folders, then review the source and trust before using a skill.",
sections: [
{
"id": "manager",
"title": "Open the skills manager",
"blocks": [
{
"code": "/skills\n/skills manage\n/skills inspect\n/skill <name>",
"lang": "Codewhale"
},
{
"p": "The manager opens without network access and shows owned roots. Turn on compatible-root scanning to inspect external folders; importing targets a Codewhale-owned root."
}
]
},
{
"id": "install",
"title": "Install into an owned folder",
"blocks": [
{
"code": "/skill install --project <spec>\n/skill install --global <spec>\n/skill trust --project <name>",
"lang": "Codewhale"
},
{
"p": "Owned roots are .codewhale/skills in your project and ~/.codewhale/skills globally. Compatible .agents/skills and .claude/skills directories are read-only import sources."
},
{
"note": "Project skills load only after you trust that workspace. A configured external skills_dir stays read-only; choosing a folder does not grant authority to mutate it."
}
]
},
{
"id": "invocation",
"title": "Choose who can load a skill",
"blocks": [
{
"p": "Frontmatter disable-model-invocation: true removes a skill from model discovery. user-invocable: false hides it from user menus and refuses explicit activation; setting both disables both paths."
},
{
"p": "A skill body enters context when loaded. The compact catalogue contains bounded names, aliases and invocation metadata."
}
]
}
],
next: [
{
"href": "/docs/claude-code",
"label": "Move from Claude Code",
"note": "Bring compatible skills and review a settings import."
},
{
"href": "/plugins",
"label": "Add plugins",
"note": "Install supported bundles through review and trust."
}
],
sourceNote: "Source: docs/SKILLS.md and docs/CLAUDE_PLUGIN_COMPAT.md."
};
@@ -15,6 +15,25 @@ export const docsTrust: DocsTrustDict = {
lede:
"Codewhale runs on your computer and talks to the model provider you choose. This page lists what goes where, what the anonymous usage count contains, and how to switch it off — as built today.",
sections: [
{
"id": "preview-request",
"title": "See the request before sending",
"blocks": [
{
"p": "/preview-request shows a redacted manifest of the next primary turn. This human command never sends a request or writes conversation or Work state."
},
{
"code": "/preview-request\n/preview-request json\n/preview-request json --prompt explain this project",
"lang": "Codewhale"
},
{
"note": "Without --prompt, route and body are unavailable. A configured classifier, hooks or pending runtime work can also prevent an exact preview; the manifest states why."
},
{
"p": "[Read the request preview contract](https://github.com/codewhale-hq/CodeWhale/blob/main/docs/PREVIEW_REQUEST.md)"
}
]
},
{
id: "boundaries",
title: "Where your work goes",
+16
View File
@@ -0,0 +1,16 @@
import type { FeaturesDict } from "../types";
export const features: FeaturesDict = {
title: "Check what Codewhale ships",
description: "Browse Codewhale commands, tools and Runtime capabilities with availability and documentation.",
notice: "This catalogue covers {count} entries in source v{version}. Names and descriptions are in English; check your installed version.",
stable: "Stable",
flagged: "Requires a flag",
experimental: "Experimental",
partial: "Partial",
preview: "Preview",
none: "Unavailable",
docs: "Read documentation",
source: "Read source entry",
exportJson: "Download feature JSON",
};
+3 -5
View File
@@ -2,13 +2,11 @@ import type { HomeDict } from "../types";
/** English reference home copy: useful work with chosen models and connected tools. */
export const home: HomeDict = {
metaTitle: "Codewhale: build with your models and tools",
metaDescription:
"Build apps, automate workflows, and work across connected tools with Codewhale. Open source, with your own model APIs or local and self-hosted inference.",
metaTitle: "Codewhale: an open-source coding agent",
metaDescription: "Codewhale is an open-source coding agent for your terminal. Read, edit and test projects with your own hosted or local models.",
heroTitle: "Build apps and automate your work.",
heroIntro:
"{brand} is an open-source agent that writes code, runs commands and works with the tools you connect. Use your existing model APIs, or run models locally and on your own servers.",
heroIntro: "{brand} is an open-source coding agent that reads files, writes code and runs commands in your terminal. Connect your existing model API or a local model, and choose which actions need approval.",
getCodewhale: "Install Codewhale",
heroInstallAria: "Install command",
exploreProduct: "Explore Codewhale",
+1 -1
View File
@@ -8,7 +8,7 @@ import type { RuntimeDict } from "../types";
export const runtime: RuntimeDict = {
metaTitle: "Runtime & Integrations · Codewhale",
metaDescription:
"Connect editors, scripts, and chat apps to Codewhale through the local Runtime API over HTTP/SSE, a baseline ACP stdio adapter, MCP servers, an early VS Code companion, and messaging bridges.",
"Connect editors, scripts, and chat apps to Codewhale through the local Runtime API over HTTP/SSE, an ACP stdio transport, MCP servers, an early VS Code companion, and messaging bridges.",
kicker: "Runtime & Integrations",
title: "Drive Codewhale from your own tools",
titleAside: "运行时与集成",
+1
View File
@@ -21,6 +21,7 @@ export const chrome: ChromeDict = {
navCommunity: "Comunidad",
navContribute: "Contribuir",
navFeatures: "Capacidades",
navProduct: "Producto",
navModels: "Modelos",
navPlugins: "Plugins",
+1 -1
View File
@@ -9,7 +9,7 @@ import type { ComputerUseDict } from "../types";
* the app shows them.
*/
export const computerUse: ComputerUseDict = {
metaTitle: "Computer Use para Mac · Codewhale",
metaTitle: "Computer Use · Vista previa · Codewhale",
metaDescription: "Descarga y configura Codewhale Computer Use para Mac. Control de aplicaciones en segundo plano, configuración de permisos y controles Pause y Stop en tus manos.",
title: "Computer Use",
lead: "Deja que Codewhale trabaje en tus aplicaciones mientras tú sigues con lo tuyo. El asistente para Mac reúne en la barra de menús los permisos, el control de aplicaciones en segundo plano y una forma de pausar o detener la entrada.",
+16
View File
@@ -0,0 +1,16 @@
import type { FeaturesDict } from "../types";
export const features: FeaturesDict = {
title: "Consulta las capacidades de Codewhale",
description: "Explora los comandos, herramientas y capacidades de Runtime de Codewhale, con disponibilidad y documentación.",
notice: "El catálogo contiene {count} entradas del código fuente v{version}. Los nombres y descripciones están en inglés; comprueba tu versión instalada.",
stable: "Estable",
flagged: "Requiere una opción",
experimental: "Experimental",
partial: "Parcial",
preview: "Vista previa",
none: "No disponible",
docs: "Leer documentación",
source: "Ver entrada del código",
exportJson: "Descargar JSON de capacidades",
};
+3 -5
View File
@@ -3,12 +3,10 @@ import type { HomeDict } from "../types";
/** Spanish home copy: useful work with chosen models and connected tools. */
export const home: HomeDict = {
metaTitle: "Codewhale: construye con tus modelos y herramientas",
metaDescription:
"Crea aplicaciones, automatiza flujos de trabajo y usa herramientas conectadas con Codewhale. Código abierto, con tus propias API de modelos o inferencia local y autoalojada.",
metaTitle: "Codewhale: agente de programación de código abierto",
metaDescription: "Codewhale es un agente de programación de código abierto para tu terminal. Lee, edita y prueba proyectos con tus modelos alojados o locales.",
heroTitle: "Crea aplicaciones y automatiza tu trabajo.",
heroIntro:
"{brand} es un agente de código abierto que escribe código, ejecuta comandos y trabaja con las herramientas que conectas. Usa las API de modelos que ya utilizas o ejecuta modelos de forma local y en tus propios servidores.",
heroIntro: "{brand} es un agente de programación de código abierto que lee archivos, escribe código y ejecuta comandos en tu terminal. Conecta tu API de modelos o un modelo local y elige qué acciones necesitan aprobación.",
getCodewhale: "Instalar Codewhale",
heroInstallAria: "Comando de instalación",
exploreProduct: "Explora Codewhale",
+1
View File
@@ -25,6 +25,7 @@ export const chrome: ChromeDict = {
navCommunity: "Communauté",
navContribute: "Contribuer",
navFeatures: "Capacités",
navProduct: "Produit",
navModels: "Modèles",
navPlugins: "Plugins",
+1 -1
View File
@@ -8,7 +8,7 @@ import type { ComputerUseDict } from "../types";
* guillemets, in line with the other French dictionaries.
*/
export const computerUse: ComputerUseDict = {
metaTitle: "Computer Use pour Mac · Codewhale",
metaTitle: "Computer Use · Aperçu · Codewhale",
metaDescription: "Téléchargez et configurez Codewhale Computer Use pour Mac : contrôle des apps en arrière-plan, configuration des autorisations et commandes Pause et Stop à portée de main.",
title: "Computer Use",
lead: "Laissez Codewhale agir dans vos apps pendant que vous continuez à travailler. L’assistant Mac regroupe dans votre barre des menus les autorisations, le contrôle des apps en arrière-plan et de quoi mettre en pause ou arrêter la saisie.",
+16
View File
@@ -0,0 +1,16 @@
import type { FeaturesDict } from "../types";
export const features: FeaturesDict = {
title: "Consultez les capacités de Codewhale",
description: "Parcourez les commandes, outils et capacités du Runtime Codewhale, avec leur disponibilité et leur documentation.",
notice: "Le catalogue contient {count} entrées du code source v{version}. Les noms et descriptions sont en anglais ; vérifiez votre version installée.",
stable: "Stable",
flagged: "Option requise",
experimental: "Expérimental",
partial: "Partiel",
preview: "Aperçu",
none: "Indisponible",
docs: "Lire la documentation",
source: "Voir le code source",
exportJson: "Télécharger le JSON des capacités",
};
+3 -5
View File
@@ -3,12 +3,10 @@ import type { HomeDict } from "../types";
/** French home copy: useful work with chosen models and connected tools. */
export const home: HomeDict = {
metaTitle: "Codewhale : créez avec vos modèles et vos outils",
metaDescription:
"Créez des applications, automatisez vos tâches et utilisez vos outils connectés avec Codewhale. Un logiciel libre, avec vos API de modèles ou votre inférence locale et auto-hébergée.",
metaTitle: "Codewhale : agent de programmation open source",
metaDescription: "Codewhale est un agent de programmation open source pour votre terminal. Lisez, modifiez et testez des projets avec vos modèles hébergés ou locaux.",
heroTitle: "Créez des applications et automatisez votre travail.",
heroIntro:
"{brand} est un agent open source qui écrit du code, exécute des commandes et utilise les outils que vous connectez. Utilisez vos API de modèles habituelles, ou exécutez des modèles en local et sur vos propres serveurs.",
heroIntro: "{brand} est un agent de programmation open source qui lit les fichiers, écrit du code et exécute des commandes dans votre terminal. Connectez votre API de modèles ou un modèle local et choisissez les actions à approuver.",
getCodewhale: "Installer Codewhale",
heroInstallAria: "Commande d'installation",
exploreProduct: "Découvrir Codewhale",
+1
View File
@@ -23,6 +23,7 @@ export const chrome: ChromeDict = {
navCommunity: "समुदाय",
navContribute: "योगदान",
navFeatures: "क्षमताएँ",
navProduct: "उत्पाद",
navModels: "मॉडल",
navPlugins: "प्लगइन",
+1 -1
View File
@@ -7,7 +7,7 @@ import type { ComputerUseDict } from "../types";
* the app shows them.
*/
export const computerUse: ComputerUseDict = {
metaTitle: "Mac के लिए Computer Use · Codewhale",
metaTitle: "Computer Use · पूर्वावलोकन · Codewhale",
metaDescription: "Mac के लिए Codewhale Computer Use डाउनलोड और सेट अप करें। बैकग्राउंड में ऐप नियंत्रण, अनुमतियों का सेटअप और आपके हाथ में Pause व Stop नियंत्रण।",
title: "Computer Use",
lead: "आप अपना काम करते रहें और Codewhale आपके ऐप्स में काम करे। Mac हेल्पर अनुमतियाँ, बैकग्राउंड में ऐप नियंत्रण और इनपुट रोकने या बंद करने का तरीका आपके मेनू बार में ले आता है।",
+16
View File
@@ -0,0 +1,16 @@
import type { FeaturesDict } from "../types";
export const features: FeaturesDict = {
title: "Codewhale की क्षमताएँ देखें",
description: "Codewhale के आदेशों, उपकरणों और Runtime क्षमताओं की उपलब्धता और दस्तावेज़ देखें।",
notice: "इस सूची में स्रोत v{version} की {count} प्रविष्टियाँ हैं। नाम और विवरण अंग्रेज़ी में हैं; अपना स्थापित संस्करण जाँचें।",
stable: "स्थिर",
flagged: "फ़्लैग आवश्यक",
experimental: "प्रयोगात्मक",
partial: "आंशिक",
preview: "पूर्वावलोकन",
none: "अनुपलब्ध",
docs: "दस्तावेज़ पढ़ें",
source: "स्रोत प्रविष्टि देखें",
exportJson: "क्षमताओं का JSON डाउनलोड करें",
};
+3 -5
View File
@@ -3,12 +3,10 @@ import type { HomeDict } from "../types";
/** Hindi home copy: useful work with chosen models and connected tools. */
export const home: HomeDict = {
metaTitle: "Codewhale: अपने मॉडल और टूल से बनाएं",
metaDescription:
"Codewhale से ऐप बनाएं, काम स्वचालित करें और जुड़े टूल इस्तेमाल करें। ओपन सोर्स, आपके मॉडल API या स्थानीय और खुद होस्ट किए गए इन्फरेंस के साथ।",
metaTitle: "Codewhale: ओपन-सोर्स कोडिंग एजेंट",
metaDescription: "Codewhale आपके टर्मिनल के लिए एक ओपन-सोर्स कोडिंग एजेंट है। अपने होस्ट किए गए या स्थानीय मॉडल से प्रोजेक्ट पढ़ें, बदलें और जाँचें।",
heroTitle: "ऐप बनाएं और अपना काम स्वचालित करें।",
heroIntro:
"{brand} एक ओपन-सोर्स एजेंट है जो कोड लिखता है, कमांड चलाता है और आपके जोड़े गए टूल के साथ काम करता है। अपने मौजूदा मॉडल API का उपयोग करें, या मॉडल को स्थानीय रूप से और अपने सर्वर पर चलाएं।",
heroIntro: "{brand} एक ओपन-सोर्स कोडिंग एजेंट है जो टर्मिनल में फ़ाइलें पढ़ता, कोड लिखता और आदेश चलाता है। अपने मॉडल API या स्थानीय मॉडल को जोड़ें और चुनें कि किन कार्रवाइयों को मंज़ूरी चाहिए।",
getCodewhale: "Codewhale इंस्टॉल करें",
heroInstallAria: "इंस्टॉल कमांड",
exploreProduct: "Codewhale देखें",
+1
View File
@@ -19,6 +19,7 @@ export const chrome: ChromeDict = {
navCommunity: "Komunitas",
navContribute: "Kontribusi",
navFeatures: "Kemampuan",
navProduct: "Produk",
navModels: "Model",
navPlugins: "Plugin",
+1 -1
View File
@@ -7,7 +7,7 @@ import type { ComputerUseDict } from "../types";
* the app shows them; formal "Anda" address matches the rest of the site.
*/
export const computerUse: ComputerUseDict = {
metaTitle: "Computer Use untuk Mac · Codewhale",
metaTitle: "Computer Use · Pratinjau · Codewhale",
metaDescription: "Unduh dan siapkan Codewhale Computer Use untuk Mac. Kendali aplikasi di latar belakang, pengaturan izin, serta kontrol Pause dan Stop di tangan Anda.",
title: "Computer Use",
lead: "Biarkan Codewhale bekerja di aplikasi Anda sementara Anda tetap bekerja. Pembantu Mac ini menghadirkan pengaturan izin, kendali aplikasi di latar belakang, dan cara menjeda atau menghentikan input langsung dari bar menu.",
+16
View File
@@ -0,0 +1,16 @@
import type { FeaturesDict } from "../types";
export const features: FeaturesDict = {
title: "Lihat kemampuan Codewhale",
description: "Jelajahi perintah, alat dan kemampuan Runtime Codewhale beserta ketersediaan dan dokumentasinya.",
notice: "Katalog ini memuat {count} entri dari sumber v{version}. Nama dan deskripsi berbahasa Inggris; periksa versi yang terpasang.",
stable: "Stabil",
flagged: "Memerlukan flag",
experimental: "Eksperimental",
partial: "Sebagian",
preview: "Pratinjau",
none: "Tidak tersedia",
docs: "Baca dokumentasi",
source: "Baca entri sumber",
exportJson: "Unduh JSON kemampuan",
};
+3 -5
View File
@@ -3,12 +3,10 @@ import type { HomeDict } from "../types";
/** Indonesian home copy: useful work with chosen models and connected tools. */
export const home: HomeDict = {
metaTitle: "Codewhale: berkarya dengan model dan alat pilihanmu",
metaDescription:
"Buat aplikasi, otomatisasikan alur kerja, dan gunakan alat terhubung dengan Codewhale. Sumber terbuka, dengan API model milikmu atau inferensi lokal dan mandiri.",
metaTitle: "Codewhale: agen pemrograman sumber terbuka",
metaDescription: "Codewhale adalah agen pemrograman sumber terbuka untuk terminal. Baca, edit dan uji proyek dengan model jarak jauh atau lokal pilihan Anda.",
heroTitle: "Buat aplikasi dan otomatisasikan pekerjaanmu.",
heroIntro:
"{brand} adalah agen sumber terbuka yang menulis kode, menjalankan perintah, dan bekerja dengan alat yang kamu hubungkan. Gunakan API model yang sudah kamu pakai, atau jalankan model secara lokal dan di servermu sendiri.",
heroIntro: "{brand} adalah agen pemrograman sumber terbuka yang membaca berkas, menulis kode dan menjalankan perintah di terminal. Hubungkan API model atau model lokal Anda dan pilih tindakan yang memerlukan persetujuan.",
getCodewhale: "Instal Codewhale",
heroInstallAria: "Perintah instalasi",
exploreProduct: "Jelajahi Codewhale",
+57
View File
@@ -1,3 +1,7 @@
import { docsClaudeCode as enDocsClaudeCode } from "./en/docs-claude-code";
import { docsClaudeCode as zhDocsClaudeCode } from "./zh/docs-claude-code";
import { docsSkills as enDocsSkills } from "./en/docs-skills";
import { docsSkills as zhDocsSkills } from "./zh/docs-skills";
/**
* Dictionary loader for the website localization layer (#3091, #4934).
*
@@ -39,6 +43,8 @@ import type {
DocsWorkDict,
DocsPetDict,
HomeDict,
FeaturesDict,
DocsPageDict,
DigestDict,
FeedDict,
CommunityDict,
@@ -48,6 +54,24 @@ import type {
RoadmapDict,
StatesDict,
} from "./types";
import { features as features0 } from "./en/features";
import { features as features1 } from "./zh/features";
import { features as features2 } from "./ja/features";
import { features as features3 } from "./vi/features";
import { features as features4 } from "./ko/features";
import { features as features5 } from "./ru/features";
import { features as features6 } from "./uk/features";
import { features as features7 } from "./es/features";
import { features as features8 } from "./pt-BR/features";
import { features as features9 } from "./fr/features";
import { features as features10 } from "./de/features";
import { features as features11 } from "./ca/features";
import { features as features12 } from "./id/features";
import { features as features13 } from "./hi/features";
import { features as features14 } from "./tr/features";
import { features as features15 } from "./it/features";
import { features as features16 } from "./pl/features";
import { features as features17 } from "./ar/features";
import { chrome as enChrome } from "./en/chrome";
import { home as enHome } from "./en/home";
import { docsGuide as enDocsGuide } from "./en/docs-guide";
@@ -382,6 +406,31 @@ const RUNTIME: Record<string, RuntimeDict> = {
zh: zhRuntime,
};
const FEATURES: Record<string, FeaturesDict> = {
"en": features0,
"zh": features1,
"ja": features2,
"vi": features3,
"ko": features4,
"ru": features5,
"uk": features6,
"es": features7,
"pt-BR": features8,
"fr": features9,
"de": features10,
"ca": features11,
"id": features12,
"hi": features13,
"tr": features14,
"it": features15,
"pl": features16,
"ar": features17,
};
export function getFeatures(locale: string): FeaturesDict {
return FEATURES[locale] ?? features0;
}
export function getChrome(locale: string): ChromeDict {
return CHROME[locale] ?? enChrome;
}
@@ -598,3 +647,11 @@ export function splitToken(template: string, token: string): string[] {
return template.split(`{${token}}`);
}
export function getDocsSkills(locale: string): DocsPageDict {
return locale === "zh" ? zhDocsSkills : enDocsSkills;
}
export function getDocsClaudeCode(locale: string): DocsPageDict {
return locale === "zh" ? zhDocsClaudeCode : enDocsClaudeCode;
}
+1
View File
@@ -23,6 +23,7 @@ export const chrome: ChromeDict = {
navCommunity: "Comunità",
navContribute: "Contribuisci",
navFeatures: "Capacità",
navProduct: "Prodotto",
navModels: "Modelli",
navPlugins: "Plugin",
+1 -1
View File
@@ -7,7 +7,7 @@ import type { ComputerUseDict } from "../types";
* the app shows them.
*/
export const computerUse: ComputerUseDict = {
metaTitle: "Computer Use per Mac · Codewhale",
metaTitle: "Computer Use · Anteprima · Codewhale",
metaDescription: "Scarica e configura Codewhale Computer Use per Mac. Controllo delle app in background, configurazione dei permessi e comandi Pause e Stop sotto il tuo controllo.",
title: "Computer Use",
lead: "Lascia che Codewhale lavori nelle tue app mentre tu continui a lavorare. L’helper per Mac porta nella barra dei menu i permessi, il controllo delle app in background e un modo per mettere in pausa o fermare l’input.",
+16
View File
@@ -0,0 +1,16 @@
import type { FeaturesDict } from "../types";
export const features: FeaturesDict = {
title: "Consulta le capacità di Codewhale",
description: "Esplora comandi, strumenti e capacità del Runtime Codewhale, con disponibilità e documentazione.",
notice: "Il catalogo contiene {count} voci del sorgente v{version}. I nomi e le descrizioni sono in inglese; verifica la versione installata.",
stable: "Stabile",
flagged: "Richiede un’opzione",
experimental: "Sperimentale",
partial: "Parziale",
preview: "Anteprima",
none: "Non disponibile",
docs: "Leggi la documentazione",
source: "Leggi la voce sorgente",
exportJson: "Scarica il JSON delle capacità",
};
+3 -5
View File
@@ -3,12 +3,10 @@ import type { HomeDict } from "../types";
/** Italian home copy: useful work with chosen models and connected tools. */
export const home: HomeDict = {
metaTitle: "Codewhale: crea con i tuoi modelli e strumenti",
metaDescription:
"Crea app, automatizza flussi di lavoro e usa strumenti connessi con Codewhale. Open source, con le tue API di modelli o inferenza locale e autogestita.",
metaTitle: "Codewhale: agente di programmazione open source",
metaDescription: "Codewhale è un agente di programmazione open source per il terminale. Leggi, modifica e testa progetti con i tuoi modelli remoti o locali.",
heroTitle: "Crea app e automatizza il tuo lavoro.",
heroIntro:
"{brand} è un agente open source che scrive codice, esegue comandi e lavora con gli strumenti che colleghi. Usa le API di modelli che già utilizzi oppure esegui modelli in locale e sui tuoi server.",
heroIntro: "{brand} è un agente di programmazione open source che legge file, scrive codice ed esegue comandi nel terminale. Collega la tua API di modelli o un modello locale e scegli quali azioni richiedono approvazione.",
getCodewhale: "Installa Codewhale",
heroInstallAria: "Comando di installazione",
exploreProduct: "Esplora Codewhale",
+1
View File
@@ -20,6 +20,7 @@ export const chrome: ChromeDict = {
navCommunity: "コミュニティ",
navContribute: "貢献",
navFeatures: "機能",
navProduct: "製品",
navModels: "モデル",
navPlugins: "プラグイン",
+1 -1
View File
@@ -8,7 +8,7 @@ import type { ComputerUseDict } from "../types";
* Japanese system UI (アクセシビリティ / 画面収録 / アプリケーション).
*/
export const computerUse: ComputerUseDict = {
metaTitle: "Mac 版 Computer Use · Codewhale",
metaTitle: "Computer Use · プレビュー · Codewhale",
metaDescription: "Mac 版 Codewhale Computer Use をダウンロードして設定します。アプリのバックグラウンド操作、権限の設定、そして人が操作する Pause と Stop のコントロールを備えています。",
title: "Computer Use",
lead: "あなたが作業を続けている間に、Codewhale がアプリの中で仕事を進めます。Mac 用ヘルパーは、権限の設定、アプリのバックグラウンド操作、入力の一時停止や停止をメニューバーにまとめます。",
+16
View File
@@ -0,0 +1,16 @@
import type { FeaturesDict } from "../types";
export const features: FeaturesDict = {
title: "Codewhale の機能を確認",
description: "Codewhale のコマンド、ツール、Runtime の機能と対応状況、ドキュメントを確認できます。",
notice: "この一覧にはソース v{version} の {count} 項目が含まれます。名前と説明は英語です。インストールしたバージョンを確認してください。",
stable: "安定",
flagged: "フラグが必要",
experimental: "実験的",
partial: "一部対応",
preview: "プレビュー",
none: "利用不可",
docs: "ドキュメントを読む",
source: "ソース項目を読む",
exportJson: "機能 JSON をダウンロード",
};
+3 -5
View File
@@ -3,12 +3,10 @@ import type { HomeDict } from "../types";
/** Japanese home copy: useful work with chosen models and connected tools. */
export const home: HomeDict = {
metaTitle: "Codewhale:自分のモデルとツールで、作りたいものを形に",
metaDescription:
"Codewhale でアプリを作り、仕事を自動化し、接続したツールを活用。オープンソースで、手持ちのモデル API やローカル・自己ホスト型の推論に対応。",
metaTitle: "Codewhale:オープンソースのコーディングエージェント",
metaDescription: "Codewhale はターミナルで動くオープンソースのコーディングエージェントです。選んだクラウドやローカルモデルでプロジェクトを読み、編集し、テストできます。",
heroTitle: "アプリを作り、仕事を自動化しましょう。",
heroIntro:
"{brand} は、コードを書き、コマンドを実行し、接続したツールを使って作業するオープンソースのエージェントです。既存のモデル API を使うことも、ローカルや自分のサーバーでモデルを動かすこともできます。",
heroIntro: "{brand} はターミナルでファイルを読み、コードを書き、コマンドを実行するオープンソースのコーディングエージェントです。モデル API やローカルモデルを接続し、承認が必要な操作を選べます。",
getCodewhale: "Codewhale をインストール",
heroInstallAria: "インストールコマンド",
exploreProduct: "Codewhale を見る",
+1
View File
@@ -23,6 +23,7 @@ export const chrome: ChromeDict = {
navCommunity: "커뮤니티",
navContribute: "기여",
navFeatures: "기능",
navProduct: "제품",
navModels: "모델",
navPlugins: "플러그인",
+1 -1
View File
@@ -8,7 +8,7 @@ import type { ComputerUseDict } from "../types";
* (손쉬운 사용, 화면 기록, 응용 프로그램).
*/
export const computerUse: ComputerUseDict = {
metaTitle: "Mac용 Computer Use · Codewhale",
metaTitle: "Computer Use · 미리 보기 · Codewhale",
metaDescription: "Mac용 Codewhale Computer Use를 다운로드하고 설정하세요. 백그라운드 앱 제어, 권한 설정, 그리고 사용자가 직접 누르는 Pause와 Stop 제어를 제공합니다.",
title: "Computer Use",
lead: "당신이 계속 일하는 동안 Codewhale이 앱 안에서 작업을 대신합니다. Mac 도우미는 권한 설정, 백그라운드 앱 제어, 입력을 일시 정지하거나 중지하는 기능을 메뉴 막대에 모아 줍니다.",
+16
View File
@@ -0,0 +1,16 @@
import type { FeaturesDict } from "../types";
export const features: FeaturesDict = {
title: "Codewhale 기능 확인",
description: "Codewhale 명령, 도구, Runtime 기능의 지원 상태와 문서를 확인하세요.",
notice: "이 목록은 소스 v{version}의 {count}개 항목을 포함합니다. 이름과 설명은 영어이며, 설치된 버전을 확인하세요.",
stable: "안정",
flagged: "플래그 필요",
experimental: "실험적",
partial: "일부 지원",
preview: "미리 보기",
none: "사용 불가",
docs: "문서 읽기",
source: "소스 항목 보기",
exportJson: "기능 JSON 다운로드",
};
+3 -5
View File
@@ -3,12 +3,10 @@ import type { HomeDict } from "../types";
/** Korean home copy: useful work with chosen models and connected tools. */
export const home: HomeDict = {
metaTitle: "Codewhale: 내 모델과 도구로 원하는 것을 만들기",
metaDescription:
"Codewhale로 앱을 만들고, 업무를 자동화하고, 연결된 도구로 작업하세요. 오픈 소스로, 기존 모델 API와 로컬 또는 자체 호스팅 추론을 사용할 수 있습니다.",
metaTitle: "Codewhale: 오픈 소스 코딩 에이전트",
metaDescription: "Codewhale은 터미널에서 실행되는 오픈 소스 코딩 에이전트입니다. 선택한 클라우드 또는 로컬 모델로 프로젝트를 읽고, 수정하고, 테스트하세요.",
heroTitle: "앱을 만들고 작업을 자동화하세요.",
heroIntro:
"{brand}는 코드를 작성하고, 명령을 실행하고, 연결한 도구로 작업하는 오픈 소스 에이전트입니다. 기존에 사용하는 모델 API를 쓰거나, 로컬과 자체 서버에서 모델을 실행하세요.",
heroIntro: "{brand}은 터미널에서 파일을 읽고 코드를 작성하며 명령을 실행하는 오픈 소스 코딩 에이전트입니다. 모델 API나 로컬 모델을 연결하고 승인이 필요한 작업을 선택하세요.",
getCodewhale: "Codewhale 설치",
heroInstallAria: "설치 명령",
exploreProduct: "Codewhale 둘러보기",
+1
View File
@@ -22,6 +22,7 @@ export const chrome: ChromeDict = {
navCommunity: "Społeczność",
navContribute: "Współtwórz",
navFeatures: "Możliwości",
navProduct: "Produkt",
navModels: "Modele",
navPlugins: "Wtyczki",
+1 -1
View File
@@ -7,7 +7,7 @@ import type { ComputerUseDict } from "../types";
* the app shows them.
*/
export const computerUse: ComputerUseDict = {
metaTitle: "Computer Use na Maca · Codewhale",
metaTitle: "Computer Use · Wersja poglądowa · Codewhale",
metaDescription: "Pobierz i skonfiguruj Codewhale Computer Use na Maca. Sterowanie aplikacjami w tle, konfiguracja uprawnień oraz przyciski Pause i Stop pod Twoją kontrolą.",
title: "Computer Use",
lead: "Pozwól Codewhale działać w Twoich aplikacjach, a sam pracuj dalej. Pomocnik na Maca zbiera w pasku menu uprawnienia, sterowanie aplikacjami w tle oraz możliwość wstrzymania lub zatrzymania wprowadzania danych.",
+16
View File
@@ -0,0 +1,16 @@
import type { FeaturesDict } from "../types";
export const features: FeaturesDict = {
title: "Sprawdź możliwości Codewhale",
description: "Przeglądaj polecenia, narzędzia i możliwości Runtime Codewhale wraz z dostępnością i dokumentacją.",
notice: "Katalog zawiera {count} wpisów ze źródła v{version}. Nazwy i opisy są po angielsku; sprawdź zainstalowaną wersję.",
stable: "Stabilne",
flagged: "Wymaga flagi",
experimental: "Eksperymentalne",
partial: "Częściowe",
preview: "Wersja poglądowa",
none: "Niedostępne",
docs: "Czytaj dokumentację",
source: "Czytaj wpis źródłowy",
exportJson: "Pobierz JSON możliwości",
};
+3 -5
View File
@@ -3,12 +3,10 @@ import type { HomeDict } from "../types";
/** Polish home copy: useful work with chosen models and connected tools. */
export const home: HomeDict = {
metaTitle: "Codewhale: twórz z własnymi modelami i narzędziami",
metaDescription:
"Twórz aplikacje, automatyzuj pracę i korzystaj z połączonych narzędzi w Codewhale. Otwarty kod, własne API modeli oraz lokalne lub samodzielnie hostowane wnioskowanie.",
metaTitle: "Codewhale: otwarty agent programistyczny",
metaDescription: "Codewhale to agent programistyczny z otwartym kodem dla terminala. Czytaj, edytuj i testuj projekty z wybranymi modelami zdalnymi lub lokalnymi.",
heroTitle: "Twórz aplikacje i automatyzuj swoją pracę.",
heroIntro:
"{brand} to agent open source, który pisze kod, uruchamia polecenia i pracuje z narzędziami, które podłączysz. Korzystaj z używanych już API modeli lub uruchamiaj modele lokalnie i na własnych serwerach.",
heroIntro: "{brand} to agent programistyczny z otwartym kodem, który czyta pliki, pisze kod i uruchamia polecenia w terminalu. Połącz API modelu lub model lokalny i wybierz działania wymagające zatwierdzenia.",
getCodewhale: "Zainstaluj Codewhale",
heroInstallAria: "Polecenie instalacji",
exploreProduct: "Poznaj Codewhale",
@@ -14,6 +14,7 @@ export const chrome: ChromeDict = {
navCommunity: "Comunidade",
navContribute: "Contribuir",
navFeatures: "Capacidades",
navProduct: "Produto",
navModels: "Modelos",
navPlugins: "Plugins",
@@ -7,7 +7,7 @@ import type { ComputerUseDict } from "../types";
* as the app shows them.
*/
export const computerUse: ComputerUseDict = {
metaTitle: "Computer Use para Mac · Codewhale",
metaTitle: "Computer Use · Prévia · Codewhale",
metaDescription: "Baixe e configure o Codewhale Computer Use para Mac. Controle de apps em segundo plano, configuração de permissões e controles humanos de Pause e Stop.",
title: "Computer Use",
lead: "Deixe o Codewhale trabalhar nos seus apps enquanto você continua trabalhando. O assistente para Mac reúne na barra de menus as permissões, o controle de apps em segundo plano e uma forma de pausar ou interromper a entrada.",
@@ -0,0 +1,16 @@
import type { FeaturesDict } from "../types";
export const features: FeaturesDict = {
title: "Confira as capacidades do Codewhale",
description: "Explore comandos, ferramentas e capacidades do Runtime do Codewhale, com disponibilidade e documentação.",
notice: "O catálogo inclui {count} entradas do código-fonte v{version}. Os nomes e descrições estão em inglês; confira sua versão instalada.",
stable: "Estável",
flagged: "Requer uma opção",
experimental: "Experimental",
partial: "Parcial",
preview: "Prévia",
none: "Indisponível",
docs: "Ler documentação",
source: "Ver entrada do código",
exportJson: "Baixar JSON de capacidades",
};
+3 -5
View File
@@ -3,12 +3,10 @@ import type { HomeDict } from "../types";
/** Brazilian Portuguese home copy: useful work with chosen models and connected tools. */
export const home: HomeDict = {
metaTitle: "Codewhale: construa com seus modelos e ferramentas",
metaDescription:
"Crie aplicativos, automatize fluxos de trabalho e use ferramentas conectadas com Codewhale. Código aberto, com suas APIs de modelos ou inferência local e auto-hospedada.",
metaTitle: "Codewhale: agente de programação de código aberto",
metaDescription: "Codewhale é um agente de programação de código aberto para seu terminal. Leia, edite e teste projetos com seus modelos hospedados ou locais.",
heroTitle: "Crie aplicativos e automatize seu trabalho.",
heroIntro:
"{brand} é um agente de código aberto que escreve código, executa comandos e trabalha com as ferramentas que você conecta. Use as APIs de modelos que você já utiliza ou execute modelos localmente e nos seus próprios servidores.",
heroIntro: "{brand} é um agente de programação de código aberto que lê arquivos, escreve código e executa comandos no terminal. Conecte sua API de modelos ou um modelo local e escolha quais ações precisam de aprovação.",
getCodewhale: "Instalar o Codewhale",
heroInstallAria: "Comando de instalação",
exploreProduct: "Explore o Codewhale",
+1
View File
@@ -19,6 +19,7 @@ export const chrome: ChromeDict = {
navCommunity: "Сообщество",
navContribute: "Участие",
navFeatures: "Возможности",
navProduct: "Продукт",
navModels: "Модели",
navPlugins: "Плагины",
+1 -1
View File
@@ -8,7 +8,7 @@ import type { ComputerUseDict } from "../types";
* UI names («Универсальный доступ», «Запись экрана», «Программы»).
*/
export const computerUse: ComputerUseDict = {
metaTitle: "Computer Use для Mac · Codewhale",
metaTitle: "Computer Use · Предварительная версия · Codewhale",
metaDescription: "Скачайте и настройте Codewhale Computer Use для Mac: фоновое управление приложениями, настройка разрешений и кнопки Pause и Stop под вашим контролем.",
title: "Computer Use",
lead: "Позвольте Codewhale работать в ваших приложениях, пока вы заняты своими делами. Помощник для Mac собирает в строке меню разрешения, фоновое управление приложениями и возможность приостановить или остановить ввод.",
+16
View File
@@ -0,0 +1,16 @@
import type { FeaturesDict } from "../types";
export const features: FeaturesDict = {
title: "Проверьте возможности Codewhale",
description: "Команды, инструменты и возможности Runtime Codewhale с доступностью и документацией.",
notice: "Каталог содержит {count} записей из исходного кода v{version}. Названия и описания на английском; проверьте установленную версию.",
stable: "Стабильно",
flagged: "Нужен флаг",
experimental: "Экспериментально",
partial: "Частично",
preview: "Предварительная версия",
none: "Недоступно",
docs: "Читать документацию",
source: "Открыть исходную запись",
exportJson: "Скачать JSON возможностей",
};
+3 -5
View File
@@ -3,12 +3,10 @@ import type { HomeDict } from "../types";
/** Russian home copy: useful work with chosen models and connected tools. */
export const home: HomeDict = {
metaTitle: "Codewhale: создавайте со своими моделями и инструментами",
metaDescription:
"Создавайте приложения, автоматизируйте работу и используйте подключённые инструменты в Codewhale. Открытый код, ваши API моделей, локальный или собственный инференс.",
metaTitle: "Codewhale: агент для программирования с открытым кодом",
metaDescription: "Codewhale — агент для программирования с открытым кодом в терминале. Читайте, редактируйте и тестируйте проекты с выбранной облачной или локальной моделью.",
heroTitle: "Создавайте приложения и автоматизируйте свою работу.",
heroIntro:
"{brand} — агент с открытым исходным кодом, который пишет код, выполняет команды и работает с подключёнными вами инструментами. Используйте привычные API моделей или запускайте модели локально и на своих серверах.",
heroIntro: "{brand} — агент для программирования с открытым кодом, который читает файлы, пишет код и запускает команды в терминале. Подключите API модели или локальную модель и выберите действия, требующие одобрения.",
getCodewhale: "Установить Codewhale",
heroInstallAria: "Команда установки",
exploreProduct: "Познакомиться с Codewhale",
+1
View File
@@ -22,6 +22,7 @@ export const chrome: ChromeDict = {
navCommunity: "Topluluk",
navContribute: "Katkı",
navFeatures: "Özellikler",
navProduct: "Ürün",
navModels: "Modeller",
navPlugins: "Eklentiler",
Loaded 100 of 137 files, more files were not shown because too many files have changed in this diff. Show more