diff --git a/apps/docs/content/blog/en/ai-native-monorepo-cli.md b/apps/docs/content/blog/en/ai-native-monorepo-cli.md new file mode 100644 index 0000000..174a7f9 --- /dev/null +++ b/apps/docs/content/blog/en/ai-native-monorepo-cli.md @@ -0,0 +1,48 @@ +--- +title: "What an AI-Native Monorepo CLI Needs to Control" +description: "An AI-native monorepo CLI should give agents a stable workspace contract, not just a folder generator." +date: "2026-05-17" +author: "One CLI Team" +tags: ["ai-native", "monorepo", "cli"] +--- + +## AI-native is an operating boundary + +An AI-native CLI is not only a command line tool that mentions agents. It is a tool that gives agents a stable boundary to operate inside. The important question is not whether an agent can edit files. The question is whether the agent can discover the workspace structure, understand which files are generated, run the right dependency commands, and report failures in a way that other tools can parse. + +For monorepos, this boundary matters more than usual. A single repository can contain a frontend, backend, documentation site, shared package, mobile app, and deployment config. Without a shared contract, every command and agent session starts by guessing. + +## What the CLI must make explicit + +One CLI treats the workspace manifest as the common contract. That means generated projects, template origin, package-manager choice, and operational intent are visible from structured data instead of scattered README prose. + +An AI-native monorepo CLI should make these facts explicit: + +- Where the workspace root is. +- Which projects are apps, services, packages, or docs. +- Which template created each project. +- Which dependency toolchain applies to each project. +- Which commands are safe to run automatically. +- Which errors have stable machine-readable codes. + +This is why `one create`, `one add`, `one templates`, and JSON output are part of the same product surface. Scaffolding starts the workspace, but the contract keeps it maintainable after the first command finishes. + +## Why agents need more than README text + +A human can read a README, compare it with the file tree, and infer missing details. A coding agent can do that too, but the result is slower and less reliable. If the agent needs to decide whether to run `pnpm install` at the root or `go mod download` inside a service, guessing from folders is not good enough. + +One CLI's bundled skill gives agents operating rules. The manifest gives them current state. Together they make agent work more deterministic: + +```bash +one templates -o json +one create my-app --yes -o json +one add nextjs-app --name web --yes -o json +``` + +The commands are useful for humans, but the JSON envelopes and stable error codes are what make them safe for automation. + +## The real differentiator + +Most scaffolders optimize the first minute of a project. An AI-native monorepo CLI has to optimize the handoff that happens after that: a person asks an agent to add a service, fix dependencies, inspect a manifest, or prepare a workspace to run. + +That is where a stable CLI contract matters. It turns a monorepo from a pile of generated files into a workspace that humans, scripts, and agents can all reason about. diff --git a/apps/docs/content/blog/en/coding-agent-workspace-setup.md b/apps/docs/content/blog/en/coding-agent-workspace-setup.md new file mode 100644 index 0000000..520a8b9 --- /dev/null +++ b/apps/docs/content/blog/en/coding-agent-workspace-setup.md @@ -0,0 +1,61 @@ +--- +title: "How Coding Agents Should Prepare a Workspace to Run" +description: "A safe workspace setup flow starts from the manifest, installs only missing dependencies, and reports exact commands." +date: "2026-05-17" +author: "One CLI Team" +tags: ["agent", "dependencies", "workspace"] +--- + +## Start from the workspace contract + +When a coding agent is asked to prepare a project to run, the first step should not be a package install. The first step is finding the workspace contract. In a One CLI workspace, that contract is `one.manifest.json`. + +The manifest tells the agent whether it is inside a One workspace, which package manager belongs at the root, and which subprojects exist. That is safer than guessing from `apps/`, `services/`, or package scripts. + +## Install by toolchain, not habit + +The common mistake is to run one install command everywhere. That works for small single-stack projects and fails in mixed workspaces. + +One CLI's agent guidance separates dependency setup by toolchain: + +- JS, TS, and Node projects install from the workspace root with the declared package manager. +- Go projects run module commands from the Go project directory. +- `go mod tidy` should be used after imports change or module metadata needs repair, not as a reflex before every read-only check. + +This distinction keeps the agent from changing dependency files unnecessarily. + +## A useful setup sequence + +A reliable agent flow looks like this: + +```bash +one templates -o json +``` + +Then inspect the manifest directly, choose the dependency path, and run only what is missing. For a Node workspace that uses pnpm, that usually means: + +```bash +pnpm install +``` + +For a Go service, it usually means: + +```bash +go mod download +``` + +The exact command should follow the workspace state, not an assumption baked into the agent prompt. + +## Report the commands, not just the result + +After setup, the agent should tell the user exactly what it ran. That makes the run reproducible and lets the user spot unnecessary actions. + +Good setup reports include: + +- The detected workspace root. +- The package manager or Go module path used. +- The exact install commands. +- Any files changed by dependency repair. +- Any command that was skipped because dependencies were already present. + +This is a small discipline, but it prevents a large class of hidden local-state problems. diff --git a/apps/docs/content/blog/en/json-cli-contracts-for-agents.md b/apps/docs/content/blog/en/json-cli-contracts-for-agents.md new file mode 100644 index 0000000..b4bd0d6 --- /dev/null +++ b/apps/docs/content/blog/en/json-cli-contracts-for-agents.md @@ -0,0 +1,46 @@ +--- +title: "Why CLI JSON Output Matters for Coding Agents" +description: "Stable JSON envelopes let agents branch on error codes and context instead of parsing human help text." +date: "2026-05-17" +author: "One CLI Team" +tags: ["json", "cli", "agent"] +--- + +## Human text is not a contract + +Human-friendly CLI output is useful in a terminal. It is not a good automation contract. Messages change with wording, localization, and formatting. If an agent has to parse sentences to decide what failed, the integration is fragile from the start. + +One CLI treats JSON output as part of the command contract. The goal is simple: agents should be able to read structured results, branch on stable fields, and report useful context back to the user. + +## Error codes beat message parsing + +The important field in a machine-readable error is the code, not the sentence. A message like "template not found" might become more helpful over time, or appear in another language. The code should stay stable. + +That is why agent workflows should prefer: + +```bash +one templates -o json +one create my-app --yes -o json +one add nextjs-app --name web --yes -o json +``` + +If a command fails, the agent can inspect `error.code` and `error.context`. It should not scrape `error.message` for meaning. + +## Context reduces redundant probing + +A good CLI error does not only say that something failed. It returns context that helps the caller recover. + +For example, if a template name is wrong, the error context can include available templates. The agent can show the user valid options without running another discovery command. If a target directory exists, the context can explain the conflicting path. + +This makes the agent loop shorter: + +1. Run command with JSON output. +2. Read stable code and context. +3. Decide whether to recover automatically or ask the user. +4. Report the exact reason. + +## JSON output is product design + +JSON output is often treated as an implementation detail. For agent-facing CLIs, it is product design. It defines what the agent can trust and what the user can audit. + +One CLI's command surface stays small, but the output contract gives it room to be used safely by scripts, CI jobs, and coding agents. That is the difference between a CLI that merely works in a terminal and a CLI that can participate in an AI-native workflow. diff --git a/apps/docs/content/blog/en/monorepo-scaffold-manifest.md b/apps/docs/content/blog/en/monorepo-scaffold-manifest.md new file mode 100644 index 0000000..82a3f1b --- /dev/null +++ b/apps/docs/content/blog/en/monorepo-scaffold-manifest.md @@ -0,0 +1,47 @@ +--- +title: "Why Monorepo Scaffolding Needs a Manifest" +description: "A monorepo scaffold should record why projects exist, not just where files were generated." +date: "2026-05-17" +author: "One CLI Team" +tags: ["manifest", "scaffold", "monorepo"] +--- + +## File layout is only the first layer + +Most scaffolders can create a folder layout. That is useful, but a monorepo needs more than folders. A workspace has projects, roles, dependencies, deployment targets, and conventions that should remain visible after the initial generation step. + +Without a manifest, later tooling has to infer intent from directory names and scripts. That might work when the repository is new, but it becomes harder as teams add services, packages, and deployment paths. + +## The manifest explains intent + +One CLI writes `one.manifest.json` so the workspace keeps a structured record of its own shape. The manifest gives future commands and agents a place to read project inventory and operational intent. + +That matters for common tasks: + +- Adding another frontend or backend with `one add`. +- Deciding where dependencies should be installed. +- Understanding which templates created the current projects. +- Keeping generated guidance aligned with the workspace. +- Letting agents inspect facts before editing files. + +The manifest is not a replacement for code. It is the map that tells tools how the code is organized. + +## Scaffolding should be reversible as knowledge + +The first scaffold command contains useful decisions: which template was chosen, which deploy target was selected, and which environment strategy applies. If those decisions disappear into files, every future tool has to rediscover them. + +A manifest keeps the decisions readable. That makes the workspace easier to automate because the next command does not have to start from zero. + +```bash +one create product-suite --yes -o json +one add nestjs-api --name api --yes -o json +one add nextjs-app --name web --yes -o json +``` + +Each step should leave behind enough structure for the next step to be safer. + +## The agent angle + +Coding agents need boundaries. A manifest lets an agent answer basic questions before acting: Am I in a One workspace? Which projects exist? What is generated? Which package manager is expected? + +That is why manifest-driven scaffolding fits AI-native development better than one-shot folder generation. The tool does not only create files. It preserves the workspace facts that agents need later. diff --git a/apps/docs/content/blog/en/one-cli-vs-general-scaffolding.md b/apps/docs/content/blog/en/one-cli-vs-general-scaffolding.md new file mode 100644 index 0000000..9959505 --- /dev/null +++ b/apps/docs/content/blog/en/one-cli-vs-general-scaffolding.md @@ -0,0 +1,46 @@ +--- +title: "One CLI vs General Scaffolding Tools" +description: "One CLI focuses on workspace contracts and agent-safe operations, not only initial project generation." +date: "2026-05-17" +author: "One CLI Team" +tags: ["scaffolding", "comparison", "workflow"] +--- + +## The difference is what happens after generation + +General scaffolding tools are useful because they save the first setup steps. They create a starter app, write config files, and get the project to a familiar baseline. That is still valuable. + +One CLI is aimed at a different problem: what happens after the files exist. A team needs to add more projects, explain the workspace to agents, install dependencies safely, configure deployment targets, and keep the structure understandable over time. + +## General scaffolding optimizes the start + +Most scaffolding tools optimize for a fast beginning: + +- Pick a framework. +- Generate the files. +- Install dependencies. +- Print a next command. + +That flow is enough for a single app. It becomes less complete when the repository is a monorepo or when coding agents need structured context. + +If later automation has to inspect folders and guess which commands are valid, the original scaffold did not leave behind enough contract. + +## One CLI optimizes the workspace lifecycle + +One CLI keeps the initial generation flow, but adds a workspace layer around it. The manifest, template registry, JSON output, and bundled skill all exist so future operations have a reliable starting point. + +The difference shows up in everyday tasks: + +- `one add` can add another project without losing workspace context. +- `one templates -o json` gives agents a parseable template catalog. +- Stable error codes let automation recover without parsing text. +- The bundled skill tells agents how to install dependencies by toolchain. +- The manifest tells tools what the workspace contains. + +This makes One CLI less like a one-time generator and more like a workspace contract manager. + +## When the distinction matters + +If you only need one tiny app, a general scaffolder may be enough. If you expect a workspace to involve multiple projects, agents, deployment paths, or repeated handoffs, the contract becomes more important than the first file write. + +One CLI is designed for that second case. It still scaffolds, but the larger purpose is to make the workspace legible to humans, scripts, and coding agents after generation. diff --git a/apps/docs/content/blog/en/template-governance-for-ai-workspaces.md b/apps/docs/content/blog/en/template-governance-for-ai-workspaces.md new file mode 100644 index 0000000..4778397 --- /dev/null +++ b/apps/docs/content/blog/en/template-governance-for-ai-workspaces.md @@ -0,0 +1,46 @@ +--- +title: "Template Governance for AI-Ready Workspaces" +description: "Templates are safer for agents when they carry conventions, dependency rules, and generated guidance together." +date: "2026-05-17" +author: "One CLI Team" +tags: ["templates", "governance", "agent"] +--- + +## Templates are policy, not only files + +A template is often treated as a bundle of starter files. In an AI-ready workspace, a template also carries policy: how dependencies are installed, how environment variables are documented, where generated files end, and where business code begins. + +If that policy is only implied by file layout, agents have to infer it. If the policy is part of the template and manifest contract, agents can check it. + +## Governance starts at creation time + +One CLI templates are meant to make the first project consistent with later operations. That means `one create` and `one add` should not only write files. They should also register enough structure for future commands to understand what was created. + +Good template governance answers: + +- What category does this project belong to? +- Which runtime and package manager does it expect? +- What default commands are safe to run? +- What environment variables need user-owned values? +- Which files are generated guidance and which are application code? + +These details help humans, but they are especially important for coding agents. + +## The agent should not invent conventions + +When an agent opens a generated workspace, it should not need to invent the workflow. It should read the manifest, follow the bundled skill, and use the documented commands. + +That means template governance has to be boring and explicit. A generated Next.js app, Go API, or documentation site should carry enough metadata for the CLI and the agent to reason about it later. + +```bash +one templates -o json +one add go-api --name api --yes -o json +``` + +The template name, project name, and command output become part of an auditable setup path. + +## Why this matters over time + +The value of governance grows after the repository changes hands. A new teammate or agent session can inspect the workspace and recover the original intent. That reduces onboarding friction and lowers the risk of local setup mistakes. + +Template governance is not about making scaffolding heavier. It is about making generated workspaces durable enough for repeated human and agent operation. diff --git a/apps/docs/content/blog/zh/ai-native-monorepo-cli.md b/apps/docs/content/blog/zh/ai-native-monorepo-cli.md new file mode 100644 index 0000000..e3bbf6f --- /dev/null +++ b/apps/docs/content/blog/zh/ai-native-monorepo-cli.md @@ -0,0 +1,48 @@ +--- +title: "AI-Native Monorepo CLI 到底要控制什么" +description: "AI-native monorepo CLI 不只是生成目录,而是给 agent 一个稳定的工作区契约。" +date: "2026-05-17" +author: "One CLI Team" +tags: ["ai-native", "monorepo", "cli"] +--- + +## AI-native 是操作边界 + +AI-native CLI 不是简单地在介绍里写上 agent。它真正要解决的是:agent 能不能在一个稳定边界里工作。关键问题不是 agent 能不能改文件,而是 agent 能不能发现 workspace 结构、知道哪些文件是生成产物、运行正确的依赖命令,并把失败结果用可解析的方式返回。 + +对 monorepo 来说,这个边界更重要。一个仓库里可能同时有前端、后端、文档站、共享包、移动端和部署配置。如果没有共同契约,每次命令执行和 agent 接手都要重新猜。 + +## CLI 必须显式表达哪些事实 + +One CLI 把 workspace manifest 当作共同契约。生成的项目、模板来源、包管理器选择和运行意图,都应该来自结构化数据,而不是散落在 README 文案里。 + +一个 AI-native monorepo CLI 至少要显式表达这些事实: + +- workspace root 在哪里。 +- 哪些项目是 app、service、package 或 docs。 +- 每个项目来自哪个模板。 +- 每个项目应该用哪类依赖工具链。 +- 哪些命令可以自动运行。 +- 哪些错误有稳定的机器可读 code。 + +这也是为什么 `one create`、`one add`、`one templates` 和 JSON 输出属于同一个产品面。脚手架负责开始项目,但契约负责让项目在第一次生成之后仍然可维护。 + +## agent 需要的不只是 README + +人可以读 README,再对照文件树推断缺失信息。agent 也可以这样做,但更慢,也更不稳定。如果 agent 要判断是在根目录运行 `pnpm install`,还是进某个服务里运行 `go mod download`,只靠目录名猜是不够的。 + +One CLI 的 bundled skill 给 agent 操作规则,manifest 给 agent 当前状态。两者配合后,agent 工作会更确定: + +```bash +one templates -o json +one create my-app --yes -o json +one add nextjs-app --name web --yes -o json +``` + +这些命令对人也有用,但真正适合自动化的是 JSON envelope 和稳定 error code。 + +## 真正的差异点 + +大多数脚手架优化的是项目开始的第一分钟。AI-native monorepo CLI 要优化的是之后的交接:人让 agent 加服务、补依赖、检查 manifest,或者准备 workspace 运行。 + +稳定的 CLI 契约就在这里产生价值。它让 monorepo 不再只是一堆生成出来的文件,而是人、脚本和 agent 都能理解的工作区。 diff --git a/apps/docs/content/blog/zh/coding-agent-workspace-setup.md b/apps/docs/content/blog/zh/coding-agent-workspace-setup.md new file mode 100644 index 0000000..b886aba --- /dev/null +++ b/apps/docs/content/blog/zh/coding-agent-workspace-setup.md @@ -0,0 +1,61 @@ +--- +title: "Coding Agent 应该怎样准备一个 workspace 运行" +description: "安全的 workspace setup 应该从 manifest 开始,只补缺失依赖,并报告执行过的精确命令。" +date: "2026-05-17" +author: "One CLI Team" +tags: ["agent", "dependencies", "workspace"] +--- + +## 先找工程契约 + +当用户让 coding agent 准备一个项目运行时,第一步不应该是安装依赖。第一步应该是找到 workspace 契约。在 One CLI 工作区里,这个契约就是 `one.manifest.json`。 + +manifest 会告诉 agent:当前目录是不是 One workspace、根目录使用什么包管理器、有哪些子项目。它比根据 `apps/`、`services/` 或 package script 猜测要安全得多。 + +## 按工具链补依赖,而不是按习惯 + +常见错误是到处运行同一个 install 命令。对单技术栈小项目可能没问题,但在混合 workspace 里很容易出错。 + +One CLI 给 agent 的规则是按工具链区分依赖安装: + +- JS、TS、Node 项目从 workspace root 使用声明的包管理器安装。 +- Go 项目在对应 Go project 目录里运行 module 命令。 +- `go mod tidy` 只在 import 变化或 module 元数据需要修复时使用,不要每次检查都习惯性运行。 + +这个区分可以减少 agent 对依赖文件的无意义改动。 + +## 一个可复用的 setup 流程 + +可靠的 agent 流程可以先从可解析命令开始: + +```bash +one templates -o json +``` + +然后直接读取 manifest,判断依赖路径,只运行缺失的部分。对于使用 pnpm 的 Node workspace,通常是: + +```bash +pnpm install +``` + +对于 Go service,通常是: + +```bash +go mod download +``` + +具体命令应该由当前 workspace 状态决定,而不是由 agent prompt 里的固定习惯决定。 + +## 报告命令,而不是只说完成 + +setup 完成后,agent 应该告诉用户自己到底执行了什么。这样过程可复现,用户也能发现不必要的动作。 + +好的 setup 报告应该包含: + +- 检测到的 workspace root。 +- 使用的包管理器或 Go module 路径。 +- 精确执行过的安装命令。 +- 因依赖修复而变化的文件。 +- 因依赖已经存在而跳过的命令。 + +这只是一个很小的纪律,但能避免很多隐藏的本地状态问题。 diff --git a/apps/docs/content/blog/zh/json-cli-contracts-for-agents.md b/apps/docs/content/blog/zh/json-cli-contracts-for-agents.md new file mode 100644 index 0000000..579e48d --- /dev/null +++ b/apps/docs/content/blog/zh/json-cli-contracts-for-agents.md @@ -0,0 +1,46 @@ +--- +title: "为什么 CLI JSON 输出对 Coding Agent 很重要" +description: "稳定的 JSON envelope 让 agent 根据 error code 和 context 分支,而不是解析给人看的文案。" +date: "2026-05-17" +author: "One CLI Team" +tags: ["json", "cli", "agent"] +--- + +## 给人看的文本不是契约 + +人类友好的 CLI 输出适合终端阅读,但不适合作为自动化契约。文案会随着表达、语言和格式变化。如果 agent 必须解析句子才能判断错误原因,这个集成从一开始就很脆弱。 + +One CLI 把 JSON 输出当作命令契约的一部分。目标很简单:agent 应该读取结构化结果,根据稳定字段分支,并把有用上下文报告给用户。 + +## error code 比解析 message 更可靠 + +机器可读错误里最重要的是 code,而不是句子。类似 “template not found” 这样的 message 以后可能变得更友好,也可能换成另一种语言。但 code 应该保持稳定。 + +所以 agent workflow 应该优先使用: + +```bash +one templates -o json +one create my-app --yes -o json +one add nextjs-app --name web --yes -o json +``` + +如果命令失败,agent 应该检查 `error.code` 和 `error.context`,而不是从 `error.message` 里抠语义。 + +## context 能减少重复探测 + +好的 CLI 错误不只是说失败了,还应该返回帮助调用方恢复的上下文。 + +例如模板名写错时,错误上下文可以携带可用模板。agent 就能直接展示有效选项,而不是再运行一次探测命令。目标目录冲突时,上下文也可以说明具体路径。 + +这样 agent 的循环会更短: + +1. 用 JSON 输出运行命令。 +2. 读取稳定 code 和 context。 +3. 判断是否能自动恢复,还是需要问用户。 +4. 报告精确原因。 + +## JSON 输出也是产品设计 + +JSON 输出经常被当作实现细节。对面向 agent 的 CLI 来说,它其实是产品设计。它定义了 agent 能信任什么,也定义了用户能审计什么。 + +One CLI 的命令表面很小,但输出契约让它可以被脚本、CI 和 coding agent 安全使用。这就是“能在终端跑”的 CLI 和“能参与 AI-native workflow”的 CLI 之间的差异。 diff --git a/apps/docs/content/blog/zh/monorepo-scaffold-manifest.md b/apps/docs/content/blog/zh/monorepo-scaffold-manifest.md new file mode 100644 index 0000000..6b2067c --- /dev/null +++ b/apps/docs/content/blog/zh/monorepo-scaffold-manifest.md @@ -0,0 +1,47 @@ +--- +title: "为什么 Monorepo 脚手架需要 manifest" +description: "monorepo 脚手架不应该只记录文件生成在哪里,还应该记录项目为什么存在。" +date: "2026-05-17" +author: "One CLI Team" +tags: ["manifest", "scaffold", "monorepo"] +--- + +## 文件结构只是第一层 + +大多数脚手架都能生成目录结构。这很有用,但 monorepo 需要的不只是目录。一个 workspace 里有项目、角色、依赖、部署目标和约定,这些信息应该在第一次生成之后继续可见。 + +如果没有 manifest,后续工具只能从目录名和脚本推断意图。仓库刚创建时也许还能工作,但随着团队继续增加服务、包和部署路径,这种推断会越来越不可靠。 + +## manifest 解释意图 + +One CLI 写入 `one.manifest.json`,让 workspace 保留一份结构化的自身描述。后续命令和 agent 都可以从 manifest 读取项目清单和运行意图。 + +这对很多常见任务都有用: + +- 用 `one add` 继续追加前端或后端。 +- 判断依赖应该安装在哪里。 +- 理解当前项目来自哪些模板。 +- 让生成的 agent 指南和 workspace 保持一致。 +- 让 agent 先读取事实,再改文件。 + +manifest 不是代码的替代品,而是告诉工具“代码如何组织”的地图。 + +## 脚手架决策应该能被再次读取 + +第一次 scaffold 命令里包含很多有价值的决定:选择了哪个模板、选择了哪个部署目标、使用哪种环境变量策略。如果这些决定只沉到文件里,未来每个工具都要重新发现。 + +manifest 会把这些决定留下来。这样下一个命令不需要从零开始猜,自动化也更安全。 + +```bash +one create product-suite --yes -o json +one add nestjs-api --name api --yes -o json +one add nextjs-app --name web --yes -o json +``` + +每一步都应该留下足够结构,让下一步更安全。 + +## agent 视角 + +coding agent 需要边界。manifest 能让 agent 在行动前回答几个基础问题:我是不是在 One workspace 里?有哪些项目?哪些是生成内容?应该使用哪个包管理器? + +这也是为什么 manifest-driven scaffolding 比一次性生成目录更适合 AI-native development。工具不只是创建文件,还会保留 agent 之后需要读取的 workspace 事实。 diff --git a/apps/docs/content/blog/zh/one-cli-vs-general-scaffolding.md b/apps/docs/content/blog/zh/one-cli-vs-general-scaffolding.md new file mode 100644 index 0000000..02627ac --- /dev/null +++ b/apps/docs/content/blog/zh/one-cli-vs-general-scaffolding.md @@ -0,0 +1,46 @@ +--- +title: "One CLI 和通用脚手架工具有什么不同" +description: "One CLI 关注 workspace 契约和 agent-safe 操作,而不只是初始化生成项目。" +date: "2026-05-17" +author: "One CLI Team" +tags: ["scaffolding", "comparison", "workflow"] +--- + +## 差异在生成之后 + +通用脚手架工具很有用,因为它们节省了最开始的 setup 步骤。它们创建 starter app、写配置文件,让项目快速进入熟悉的基础状态。这件事仍然有价值。 + +One CLI 面向的是另一个问题:文件已经存在之后怎么办。团队还需要继续加项目、向 agent 解释 workspace、安全安装依赖、配置部署目标,并让结构长期保持可理解。 + +## 通用脚手架优化项目开始 + +大多数脚手架工具优化的是快速开始: + +- 选择框架。 +- 生成文件。 +- 安装依赖。 +- 打印下一条命令。 + +这个流程对单个 app 足够。但当仓库变成 monorepo,或者 coding agent 需要结构化上下文时,它就不完整了。 + +如果后续自动化还要检查目录并猜哪些命令有效,就说明最初的脚手架没有留下足够契约。 + +## One CLI 优化 workspace 生命周期 + +One CLI 保留初始化生成流程,但在外面加了一层 workspace。manifest、template registry、JSON output 和 bundled skill 都是为了让未来操作有可靠起点。 + +差异会体现在日常任务里: + +- `one add` 可以在不丢失 workspace 上下文的情况下追加项目。 +- `one templates -o json` 给 agent 一个可解析的模板清单。 +- 稳定 error code 让自动化不需要解析文本也能恢复。 +- bundled skill 告诉 agent 如何按工具链安装依赖。 +- manifest 告诉工具当前 workspace 里到底有什么。 + +这让 One CLI 不只是一次性生成器,更像 workspace contract manager。 + +## 什么时候这个区别重要 + +如果你只需要一个很小的单体 app,通用脚手架可能就够了。如果你预期 workspace 会包含多个项目、agent、部署路径或反复交接,那么契约比第一次写文件更重要。 + +One CLI 面向的是第二种情况。它仍然负责脚手架,但更大的目标是让生成后的 workspace 能被人、脚本和 coding agent 持续理解。 diff --git a/apps/docs/content/blog/zh/template-governance-for-ai-workspaces.md b/apps/docs/content/blog/zh/template-governance-for-ai-workspaces.md new file mode 100644 index 0000000..50d91bc --- /dev/null +++ b/apps/docs/content/blog/zh/template-governance-for-ai-workspaces.md @@ -0,0 +1,46 @@ +--- +title: "面向 AI Workspace 的模板治理" +description: "当模板同时携带约定、依赖规则和生成说明时,agent 操作会更安全。" +date: "2026-05-17" +author: "One CLI Team" +tags: ["templates", "governance", "agent"] +--- + +## 模板不只是文件,也是规则 + +模板经常被理解成一组起步文件。对 AI-ready workspace 来说,模板还承载规则:依赖怎么安装、环境变量怎么说明、哪些文件是生成说明、哪些文件开始属于业务代码。 + +如果这些规则只隐含在文件结构里,agent 就只能推断。如果规则进入模板和 manifest 契约,agent 就可以检查。 + +## 治理从创建时开始 + +One CLI 模板的目标,是让第一个项目和后续操作保持一致。这意味着 `one create` 和 `one add` 不应该只写文件,还应该登记足够结构,让未来命令知道自己创建了什么。 + +好的模板治理要回答这些问题: + +- 这个项目属于哪个类别。 +- 它期望什么 runtime 和包管理器。 +- 哪些默认命令可以安全运行。 +- 哪些环境变量需要用户自己填写。 +- 哪些文件是生成指南,哪些是应用代码。 + +这些信息对人有用,对 coding agent 更重要。 + +## agent 不应该发明约定 + +当 agent 打开一个生成 workspace 时,它不应该临时发明工作流。它应该读取 manifest,遵循 bundled skill,使用文档化命令。 + +这意味着模板治理必须足够明确。生成的 Next.js app、Go API 或文档站,都应该带着让 CLI 和 agent 后续理解它的元数据。 + +```bash +one templates -o json +one add go-api --name api --yes -o json +``` + +模板名、项目名和命令输出共同构成一条可审计的 setup 路径。 + +## 为什么时间越长越重要 + +治理的价值会在仓库交接之后变大。新的团队成员或新的 agent session 可以检查 workspace,并恢复当初的设计意图。这会降低上手成本,也减少本地 setup 误操作。 + +模板治理不是为了让脚手架更重,而是为了让生成的 workspace 足够耐用,可以被人和 agent 反复操作。 diff --git a/apps/docs/public/llms.txt b/apps/docs/public/llms.txt new file mode 100644 index 0000000..a83a0f6 --- /dev/null +++ b/apps/docs/public/llms.txt @@ -0,0 +1,57 @@ +# One CLI + +> One CLI is a Go-based scaffolding and governance tool for AI-native monorepo workspaces. + +Canonical site: https://1cli.dev/ + +## What it is + +One CLI creates and manages AI-ready workspaces with a manifest, reusable templates, local configuration, environment-variable flows, container and deploy helpers, JSON command output, and a bundled agent skill. + +Use it when a coding agent or engineer needs a predictable workspace contract instead of ad hoc project bootstrapping. + +## Core documentation + +- Quick start: https://1cli.dev/en/docs/quick-start/ +- Installation: https://1cli.dev/en/docs/installation/ +- CLI overview: https://1cli.dev/en/docs/cli-overview/ +- Manifest reference: https://1cli.dev/en/docs/manifest/ +- Templates: https://1cli.dev/en/docs/templates/ +- Template examples: https://1cli.dev/en/templates/ +- Agent skills: https://1cli.dev/en/docs/skills/ +- Error codes: https://1cli.dev/en/docs/error-codes/ + +## Key concepts + +- `one create`: create a workspace or apply a preset. +- `one add`: add a project from a template to an existing workspace. +- `one templates`: list available templates. +- `one configure`: store local environment, deploy, and container settings. +- `one env`: manage environment variables. +- `one run`: run a project with the selected environment. +- `one deploy`: deploy configured projects. +- `one container`: build and push container images. +- `one serve`: open the local configuration UI. +- `one skills install`: install the bundled One CLI agent skill. + +## AI and agent usage + +The site explains how agents should work from `one.manifest.json`, prefer JSON output, respect stable error codes, and install only missing dependencies according to project type. + +Recommended entry points for AI summarizers: + +- https://1cli.dev/en/docs/ai-native/ +- https://1cli.dev/en/docs/skills/ +- https://1cli.dev/en/blog/ai-native-monorepo-cli/ +- https://1cli.dev/en/blog/coding-agent-workspace-setup/ +- https://1cli.dev/en/blog/json-cli-contracts-for-agents/ +- https://1cli.dev/en/blog/monorepo-scaffold-manifest/ +- https://1cli.dev/en/blog/template-governance-for-ai-workspaces/ +- https://1cli.dev/en/blog/one-cli-vs-general-scaffolding/ +- https://1cli.dev/en/blog/agent-skill-context/ +- https://1cli.dev/en/blog/manifest-as-contract/ +- https://1cli.dev/en/blog/preset-id-boundary/ + +## Languages + +The documentation is available in Chinese and English under `/zh/` and `/en/`. Prefer the matching language URL when citing. diff --git a/apps/docs/src/app/(home)/home-page.tsx b/apps/docs/src/app/(home)/home-page.tsx index 8ee50f7..1b3844b 100644 --- a/apps/docs/src/app/(home)/home-page.tsx +++ b/apps/docs/src/app/(home)/home-page.tsx @@ -16,7 +16,6 @@ import { } from "lucide-react"; import { defaultLocale, - htmlLang, localeLabels, localizedBlogPath, localizedDocsPath, @@ -27,6 +26,12 @@ import { BrandMark } from "@/components/brand-mark"; import { HomeHeroCanvas } from "./hero-canvas"; import { HomeCopyButton } from "./home-template-preview"; import { WorkflowSidebarNav, type WorkflowNavIcon } from "./workflow-nav"; +import { + createPageMetadata, + jsonLdScriptProps, + softwareApplicationJsonLd, + websiteJsonLd, +} from "@/lib/seo"; const installCommand = "curl -fsSL https://1cli.dev/install.sh | bash"; @@ -783,17 +788,13 @@ const commandSlugs = commandNames.map((command) => command.replace(/\s+/g, "-")) export function generateHomeMetadata(lang: Locale): Metadata { const text = homeCopy[lang]; - return { + return createPageMetadata({ title: text.meta.title, description: text.meta.description, - alternates: { - canonical: localizedHomePath(lang), - languages: alternateHomeLanguages(), - }, - other: { - "content-language": htmlLang[lang], - }, - }; + path: localizedHomePath(lang), + locale: lang, + alternates: alternateHomeLanguages(), + }); } export function LocalizedHomePage({ lang }: { lang: Locale }) { @@ -801,6 +802,12 @@ export function LocalizedHomePage({ lang }: { lang: Locale }) { return (
+ {children} diff --git a/apps/docs/src/app/robots.ts b/apps/docs/src/app/robots.ts new file mode 100644 index 0000000..9226cbd --- /dev/null +++ b/apps/docs/src/app/robots.ts @@ -0,0 +1,15 @@ +import type { MetadataRoute } from "next"; +import { siteUrl } from "@/lib/seo"; + +export const dynamic = "force-static"; + +export default function robots(): MetadataRoute.Robots { + return { + rules: { + userAgent: "*", + allow: "/", + }, + sitemap: `${siteUrl}/sitemap.xml`, + host: siteUrl, + }; +} diff --git a/apps/docs/src/app/sitemap.ts b/apps/docs/src/app/sitemap.ts index 4678762..1bfd005 100644 --- a/apps/docs/src/app/sitemap.ts +++ b/apps/docs/src/app/sitemap.ts @@ -5,10 +5,9 @@ import { localizedBlogPath, } from "@/i18n"; import { getAllBlogPosts } from "@/lib/blog"; +import { siteUrl } from "@/lib/seo"; import { source } from "@/lib/source"; -const siteUrl = "https://1cli.dev"; - export const dynamic = "force-static"; export default function sitemap(): MetadataRoute.Sitemap { diff --git a/apps/docs/src/lib/blog.ts b/apps/docs/src/lib/blog.ts index 1a6e581..c3bfc44 100644 --- a/apps/docs/src/lib/blog.ts +++ b/apps/docs/src/lib/blog.ts @@ -20,16 +20,29 @@ type Frontmatter = Record; const contentRoot = path.join(process.cwd(), "content", "blog"); const repoContentRoot = path.join(process.cwd(), "apps", "docs", "content", "blog"); +// Module-level cache to avoid O(n²) build time when computing related posts +const blogPostsCache = new Map(); + export function getBlogPosts(lang: Locale) { + if (blogPostsCache.has(lang)) { + return blogPostsCache.get(lang)!; + } + const root = getBlogRoot(); const dir = path.join(root, lang); - if (!fs.existsSync(dir)) return []; + if (!fs.existsSync(dir)) { + blogPostsCache.set(lang, []); + return []; + } - return fs + const posts = fs .readdirSync(dir) .filter((file) => file.endsWith(".md")) .map((file) => readBlogPostFromFile(lang, path.join(dir, file))) .sort((a, b) => b.date.localeCompare(a.date)); + + blogPostsCache.set(lang, posts); + return posts; } export function getAllBlogPosts() { diff --git a/apps/docs/src/lib/seo.ts b/apps/docs/src/lib/seo.ts new file mode 100644 index 0000000..e919556 --- /dev/null +++ b/apps/docs/src/lib/seo.ts @@ -0,0 +1,210 @@ +import type { Metadata } from "next"; +import { htmlLang, type Locale } from "@/i18n"; + +export const siteUrl = "https://1cli.dev"; +export const siteName = "One CLI"; +export const defaultDescription = + "One CLI is a scaffolding and governance tool for AI-native monorepo workspaces, templates, manifests, local configuration, and agent-ready command flows."; + +type PageMetadataInput = { + title: string; + description?: string; + path: string; + locale?: Locale; + alternates?: Record; + type?: "website" | "article"; + images?: string[]; +}; + +type ArticleJsonLdInput = { + title: string; + description?: string; + path: string; + locale: Locale; + datePublished?: string; + dateModified?: string; + author?: string; + tags?: string[]; + section?: string; +}; + +type ItemListInput = { + name: string; + description?: string; + items: Array<{ + name: string; + path: string; + description?: string; + }>; +}; + +export function absoluteUrl(path = "/") { + return new URL(path, siteUrl).toString(); +} + +export function createPageMetadata({ + title, + description = defaultDescription, + path, + locale, + alternates, + type = "website", + images, +}: PageMetadataInput): Metadata { + return { + title, + description, + alternates: { + canonical: path, + languages: alternates, + }, + openGraph: { + type, + title, + description, + url: absoluteUrl(path), + siteName, + locale: locale ? openGraphLocale(locale) : undefined, + alternateLocale: locale ? openGraphAlternateLocales(locale) : undefined, + images, + }, + twitter: { + card: images && images.length > 0 ? "summary_large_image" : "summary", + title, + description, + images, + }, + other: locale + ? { + "content-language": htmlLang[locale], + } + : undefined, + }; +} + +export function jsonLdScriptProps(data: unknown) { + return { + type: "application/ld+json", + dangerouslySetInnerHTML: { + __html: JSON.stringify(data).replace(/) { + return { + "@context": "https://schema.org", + "@type": "BreadcrumbList", + itemListElement: items.map((item, index) => ({ + "@type": "ListItem", + position: index + 1, + name: item.name, + item: absoluteUrl(item.path), + })), + }; +} + +export function itemListJsonLd({ name, description, items }: ItemListInput) { + return { + "@context": "https://schema.org", + "@type": "ItemList", + name, + description, + itemListElement: items.map((item, index) => ({ + "@type": "ListItem", + position: index + 1, + url: absoluteUrl(item.path), + name: item.name, + description: item.description, + })), + }; +} + +function organizationJsonLd() { + return { + "@type": "Organization", + name: "1CLI Team", + url: siteUrl, + logo: absoluteUrl("/brand/icon.svg"), + }; +} + +function openGraphLocale(locale: Locale) { + return locale === "zh" ? "zh_CN" : "en_US"; +} + +function openGraphAlternateLocales(locale: Locale) { + return locale === "zh" ? ["en_US"] : ["zh_CN"]; +}