OpenClaw 中观察到的代码风格约定

本文档基于代码库分析,记录了关于 OpenClaw 代码格式化、linting 和 TypeScript 配置的观察。这些约定确保一致性并通过 CI 检查。

Linter: Oxlint(不是 ESLint)

OpenClaw 使用 Oxlint,而不是 ESLint。配置在 .oxlintrc.json 中。

关键配置

{
  "categories": {
    "correctness": "error",
    "perf": "error",
    "suspicious": "error"
  },
  "rules": {
    "typescript/no-explicit-any": "error",
    "curly": "error"
  }
}

关键规则

  • typescript/no-explicit-any: "error" - 永远不要使用 any 类型(严格执行)
  • curly: "error" - 始终为控制流语句使用大括号
  • 类别作为错误 - 正确性、性能和可疑模式都是错误,而不是警告

Formatter: Oxfmt(不是 Prettier)

OpenClaw 使用 Oxfmt,而不是 Prettier。配置在 .oxfmtrc.jsonc 中。

关键配置

{
  "indent_width": 2,
  "use_tabs": false,
  "experimental": {
    "sort_imports": true
  }
}

格式化规则

  • 2 空格缩进,不使用制表符
  • 启用实验性导入排序 - 导入语句会自动排序
  • Oxfmt 处理所有格式化;无需运行 Prettier

TypeScript 配置

TypeScript 配置在 tsconfig.json 中,启用了严格模式。

关键设置

{
  "compilerOptions": {
    "strict": true,
    "target": "ES2023",
    "module": "NodeNext",
    "moduleResolution": "NodeNext",
    "experimentalDecorators": true,
    "noEmit": true
  }
}

值得注意的设置

  • strict: true - 启用所有严格类型检查选项
  • experimentalDecorators: true - Control UI Lit 组件中的遗留装饰器所需
  • noEmit: true - TypeScript 仅用于类型检查,不用于编译
  • ES2023 目标 - 可使用现代 JavaScript 功能
  • NodeNext 模块解析 - 支持在导入中使用 .js 扩展名的 ESM

类型定义偏好

优先使用 type 而不是 interface

对于对象形状,代码库优先使用 type 而不是 interface

观察到的模式:

/**
 * Context for gateway operations.
 */
export type GatewayContext = {
  tenantId: string;
  requestId: string;
  timestamp: number;
};

不是:

export interface GatewayContext {
  tenantId: string;
  requestId: string;
  timestamp: number;
}

始终包含 JSDoc

公共类型和函数应该有 JSDoc 注释来解释其目的。

贡献文档中的关键规则

这些规则在 CONTRIBUTING.mdCLAUDE.md 中明确记录:

永远不要禁用类型安全

  • 永远不要使用 @ts-nocheck - 修复类型错误而不是抑制它们
  • 永远不要禁用 no-explicit-any - 始终提供显式类型
  • 如果您无法正确输入某些内容,请寻求指导而不是使用 any

永远不要使用原型变异

  • 永远不要变异原型来共享行为
  • 改用 extends - 适当的类继承或组合

不好:

SomeClass.prototype.newMethod = function() { ... };

好:

class ExtendedClass extends SomeClass {
  newMethod() { ... }
}

文件大小目标

  • 目标: 每个文件约 500-700 行代码
  • 将较大的文件拆分为专注的模块
  • 复杂模块的例外(需要理由)

产品命名

  • 产品名称: "OpenClaw" - 用于面向用户的消息和文档
  • CLI/配置/路径: "openclaw" - 用于命令、配置文件和目录名称

示例:

// 用户消息
console.log("Welcome to OpenClaw!");

// 配置文件路径
const configPath = path.join(homeDir, ".openclaw", "config.json");

错误处理模式

使用带有自动脱敏的 formatErrorMessage()

代码库使用集中式错误格式化函数,该函数会自动脱敏敏感信息。

观察到的模式:

import { formatErrorMessage, redactSensitiveText } from "./utils/error-utils.js";

try {
  // operation
} catch (error) {
  const message = formatErrorMessage(error, "Operation failed");
  logger.error(message);
}

自动脱敏

formatErrorMessage() 自动调用 redactSensitiveText() 来删除:

  • API 密钥
  • 令牌
  • 密码
  • 文件路径(部分脱敏)

Barrel 导出

选择性,而非通用

代码库选择性地使用 barrel 导出(index.ts):

  • 有些模块有 index.ts - 重新导出公共 API
  • 有些模块没有 - 从特定文件直接导入

不是通用模式 - 在添加 barrel 导出之前检查现有模块结构。

运行 Linting 和格式化

# 运行 Oxlint
pnpm lint

# 运行 Oxfmt(格式检查)
pnpm format:check

# 运行 Oxfmt(格式写入)
pnpm format

# 运行所有检查(包括 TypeScript 类型检查)
pnpm check

Pre-Commit 钩子

Pre-commit 钩子(通过 prek install 安装)在提交前自动运行 Oxlint 和 Oxfmt。有关详细信息,请参阅 PR 和提交约定

为什么这很重要

遵循这些约定可确保:

  1. CI 通过 - Linting 和格式化检查是 CI 的一部分
  2. 一致性 - 整个代码库中的代码看起来相同
  3. 类型安全 - 严格的 TypeScript 及早发现错误
  4. 安全性 - 自动脱敏防止敏感数据泄露
  5. 可审查性 - 一致的风格使代码审查更容易

交叉引用

  • 测试模式: 测试文件组织和结构
  • PR 和提交约定: Pre-commit 钩子和质量门控
  • 错误处理模式 (planned): 详细的错误处理模式