Composio CLI 架构深度解析:基于 Effect 生态与 Bun 的命令行工程实践
【免费下载链接】composioComposio powers 1000+ toolkits, tool search, context management, authentication, and a sandboxed workbench to help you build AI agents that turn intent into action.项目地址: https://gitcode.com/GitHub_Trending/co/composio
Composio CLI(@composio/cli)是 Composio 平台面向开发者的官方命令行工具,用于登录认证、管理 toolkits/tools/triggers、生成类型桩代码以及运行 agent 工作流。本文以仓库中 ts/packages/cli/CLAUDE.md 为骨架,结合源码深入剖析其基于Effect.ts 生态与Bun构建的服务化架构、命令体系、输出契约与工程规范,帮助读者理解这一现代 CLI 的设计思路,并掌握其关键配置、命令与扩展方式。
CLI 概览与仓库结构
@composio/cli位于 ts/packages/cli,发布产物为composio可执行文件(package.json中bin指向./bin/composio.mjs)。其核心特征:
- 运行时:基于Bun,开发时通过
bun run src/bin.ts启动,构建二进制时使用bun run ./scripts/build-binary.ts(见 package.json)。 - 依赖注入:采用 Effect 生态的 Layer 机制实现服务化架构,控制流使用
Effect.gen生成器语法,错误处理使用结构化类型。 - CLI 框架:使用
effect/unstable/cli的Command.make()/Command.runWith()构建命令树与解析参数。 - TypeScript 版本固定:该包将
typescript依赖固定在 TypeScript 6(catalog:ts6),因为src/generation/typescript/*依赖 JS compiler API,而 TS7(tsgo)不再提供该 API。此固定仅影响import ts from 'typescript'的解析,typecheck 脚本调用的tsc二进制仍来自 workspace 根(TS7)。
从源码目录结构看,CLI 源码按职责清晰分层:
src/bin.ts与src/cli-main.ts:入口与顶层 Layer 组装src/commands/:全部顶层命令与子命令组(*.cmd.ts)src/services/:Effect 服务(认证、仓库、终端 UI、二进制升级等)src/effects/:可复用的 Effect 计算src/models/:Effect Schema 数据模型src/generation/:composio generate {ts,py}代码生成管线src/effect-errors/:错误捕获、source-map 栈追踪与格式化输出
入口与启动流程:bin.ts → cli-main.ts
bin.ts:轻量引导层
src/bin.ts 是唯一直接读取process.argv的地方,此后所有消费者都接收规范化后的 argv。引导层做三件事:
- 剥离内部
--telemetry-debug标志(stripTelemetryDebugFlag)。 - 识别后台 worker 调用(analytics 事件分发),若为后台 worker,则仅提供最小 Layer 集合并通过
BunRuntime.runMain运行。 - 否则动态导入
cli-main.ts并调用runCli,由后者组装完整的 Effect Layer 栈。
cli-main.ts:Layer 组装与错误契约
src/cli-main.ts 是运行器的核心。它组合了完整的 Layer 栈(layers变量,约 25 个 Layer),关键成员包括:
CliConfigLive:CliConfig.layer(ComposioCliConfig),仅启用GlobalFlag.Help内建标志(详见下文配置小节)。ComposioUserContextLive:从~/.composio/读取用户认证状态。ComposioSessionRepositoryLive:OAuth2 会话管理。ComposioToolkitsRepositoryCachedLive:带文件缓存的 toolkits/tools API 客户端。UpgradeBinaryLive:从 GitHub Releases 自更新二进制。BunFileSystem.layer、BunPath.layer、BunServices.layer、FetchHttpClient.layer:Bun 运行时集成(Effect v4 中BunContext已不存在,BunServices.layer是聚合替代)。
Help 渲染与退出码契约:Command.runWith会自行渲染帮助文本与解析/校验错误(输出到正确的流),随后以CliError.ShowHelp重新失败。该错误携带两个 Runtime 标记:[Runtime.errorReported] = false(抑制runMain的自动错误日志)与[Runtime.errorExitCode](裸--help为 0,伴随解析错误为 1)。因此cli-main.ts的 sandbox 兜底处理器对ShowHelp采用Effect.failCause原样转发,绝不自行打印,避免输出重复;自定义teardown通过Runtime.getErrorExitCode从压缩后的失败中读取退出码。
错误捕获:真实命令执行失败经由自定义的effect-errors/模块捕获(source-map 栈追踪、Effect span 时间线、格式化输出),见 src/effect-errors。
命令体系:Command.make() 与命令树
所有命令使用effect/unstable/cli的Command.make()模式。顶层命令文件以.cmd.ts结尾;嵌套命令组位于各自子目录中,以<group>.cmd.ts作为入口。根命令树在 src/commands/index.ts 中通过Command.withSubcommands组装。
顶层命令一览
| 组 / 命令 | 用途 |
|---|---|
version | 显示 CLI 版本(支持--check检查更新) |
whoami | 显示当前登录用户信息(管道输出时向 stdout 写原始 API key,见输出约定) |
login | 浏览器跳转或直接 user/API key 登录(--no-browser、--no-wait、--key、--user-api-key、--org) |
logout | 清除已存储的 API key |
signup | 创建 Composio 账号 |
upgrade | 从 GitHub Releases 自更新二进制 |
init | 在当前目录初始化 Composio 项目 |
install | 配置 shell 集成(PATH 与补全) |
generate {ts,py} | 生成类型桩(无子命令时自动检测项目语言) |
agent | 管理 AI agent 预设 |
toolkits | 列出 / 查看 / 版本化 toolkits |
tools | 列出 / 查看 /execute工具 |
triggers | 列出 / 管理 trigger 类型 |
auth-configs | 管理 auth-config 资源(ac_*) |
connected-accounts | 管理已连接账号(ca_*) |
connections | connected-account 流程的别名 / 辅助命令 |
orgs | 管理组织 |
projects | 管理项目 |
local-tools | 管理本地 toolkits(通过@composio/cli-local-tools) |
logs | 查看工具执行日志(logs-cmd/) |
config | 读写 CLI 配置 |
listen | 监听事件(实验特性) |
proxy | 代理已认证的 API 请求 |
run | 运行保存的脚本 / 预设 |
dev | 仅开发者使用的工具 |
artifacts | 管理生成的产物 |
参数声明与 Feature Flag
命名选项使用Flag.string()、Flag.boolean()、Flag.integer()、Flag.choice()、Flag.directory()(均来自effect/unstable/cli);位置参数使用Argument.string()/Argument.variadic()。二者共享.withDefault/.withDescription/.withAlias/.optional组合子。Feature flags 定义在 src/commands/feature-tags.ts 与 src/experimental-features.ts。
argv 预处理与特殊路由
runWithConfig在把 argv 交给解析器前做了一系列规范化(见 src/commands/index.ts):
normalizeVersionFlag:composio --version/composio -v被重写为version命令,使三者输出字节级一致(裸 semver,经ui.output())。这是GlobalFlag.Version未启用的原因——避免composio <subcommand> --version落入 v4 的<name> v<version>横幅。splitRunPassthroughArgs:composio run需要把形如--flag value的 token 原样转发给用户脚本。由于 v4 的 CLI lexer 将每个-前缀 token 视为选项候选,且--分隔只作用于第一层解析,该函数将 passthrough tail 从 argv 中分离,经RunPassthroughArgsservice 以 out-of-band 方式提供给runhandler。normalizeHiddenDebugFlags:剥离--perf-debug、--tool-debug、--acp-only等隐藏调试标志,以CliDebugFlags作为命令输入而非进程级状态。- 帮助路由:
isRootHelp/matchSubcommandHelp匹配根帮助与子命令帮助,走自定义的printRootHelp/printSubcommandHelp(见root-help.ts);--help/-h被列入EXPLICIT_STDOUT_FLAGS,显式请求帮助时框架渲染走 stdout,其余场景框架渲染被重定向到 stderr(见下文输出约定)。
服务层:src/services/
服务是Context.Service类,导出<Name>Shape类型与显式static readonly DefaultLayer(Layer.effect/Layer.sync,依赖通过Layer.provide注入)。测试时用Service.of({ ... })构建替身,没有生成的访问器或构造函数。
核心服务一览
| 服务 | 用途 |
|---|---|
ComposioUserContext | 认证状态——读写~/.composio/user-config.json,合并环境变量 |
ComposioSessionRepository | 创建 OAuth2 会话,轮询直到linked状态 |
ComposioToolkitsRepository | API 客户端——拉取 toolkits、tools、trigger 类型;校验版本 |
ComposioToolkitsRepositoryCached | 基于基础仓库的装饰器,带文件缓存与优雅降级 |
NodeOs | OS 抽象(homedir、platform、arch) |
JsPackageManagerDetector | 检测 npm/pnpm/yarn/bun,用于生成安装指引 |
UpgradeBinary | 从 GitHub Releases 拉取最新版本,下载并替换二进制 |
OS 凭据存储使用兄弟包@composio/cli-keyring(macOS Keychain / Linux Secret Service)。
用户上下文与凭据存储细节
从 src/services/user-context.ts 的源码看,API key 的存储遵循安全优先级:
- 环境变量优先:
COMPOSIO_USER_API_KEY(经APP_CONFIG['USER_API_KEY']读取)优先于一切磁盘存储。 - OS keyring:keyring 服务标识为
com.composio.cli/default。CLI 配置中的security字段决定后端:"auto"与"json"使用传统明文路径(user_data.json),"keychain-subprocess"使用子进程后端(默认),"keychain"使用实验性 FFI 路径(需要 Developer ID 签名的二进制以避免系统弹窗)。 - 明文回退:当 keyring 不可用(如无头 Linux / 容器 / CI),API key 会以明文写入
user_data.json,CLI 始终偏好“继续工作 + 明文回退”而非崩溃。读取时若 keyring 命中,会自动清理磁盘上的陈旧明文并迁移(Migrating legacy api_key from user_data.json to the OS keyring)。
所有写盘操作经atomicWritePrivateFileString原子写入并确保私有文件权限(ensurePrivateFileMode)。
缓存仓库与客户端同步
ComposioToolkitsRepositoryCached是ComposioToolkitsRepository的 Layer 包装(见 src/services/composio-clients-cached.ts)。修改composio-clients.ts时必须同步检查缓存版本:方法的新增、删除、签名变更与新导出的错误类型必须保持同步。每类方法需决策“缓存还是直通”——校验类方法通常直通,拉取类方法通常缓存。缓存文件位于~/.composio/缓存目录:toolkits.json、tools.json、tools-as-enums.json、trigger-types.json(文件名定义于 src/constants.ts 的CACHE_FILENAMES)。
配置体系
CLI 框架配置(ComposioCliConfig)
src/cli-config.ts 定义了唯一的CliConfig定制:
export const ComposioCliConfig = { builtIns: [GlobalFlag.Help], } satisfies Partial<CliConfig.CliConfig.Service>;要点:
- Effect v4 的
CliConfig.Service形状缩减为单一字段builtIns——Command.runWith在命令树每一层接受的内建全局标志列表。Composio 只保留--help/-h,其余内建(--version、--wizard、--completions、--log-level)全部剔除。 GlobalFlag.Version刻意缺席:composio --version/-v被normalizeVersionFlag重写为version命令(见上文),保证三种拼写输出一致。- v3 的
autoCorrectLimit与isCaseSensitive在 v4 中没有对应配置:v4 解析器无条件计算 “Did you mean?” 建议(internal/auto-suggest.ts,无禁用开关),且不做任何大小写折叠(精确匹配)。这两点 Composio 都乐于接受,因此不再复刻。 - Composio 不提供自定义
CliOutput.Formatter——帮助渲染使用 v4 的CliOutput.defaultFormatter()。
常量与环境变量前缀
src/constants.ts 定义了:
APP_ENV_CONFIG_KEY_PREFIX = 'COMPOSIO_':用户环境变量前缀。DEBUG_OVERRIDE_ENV_CONFIG_KEY_PREFIX = 'DEBUG_OVERRIDE_':调试覆盖前缀。USER_CONFIG_FILE_NAME:用户配置文件名(user-config.json,位于~/.composio/)。CLI_CONFIG_FILE_NAME = 'config.json':CLI 通用配置。- 项目级文件:
project.json、.env(每目录 CLI 配置覆盖)、.composio/(每目录 Composio 配置目录)。 - 版本来源:发布构建将
__COMPOSIO_CLI_RELEASE_VERSION__替换为精确的 GitHub release 版本;私有包版本0.0.0-development仅是源码/开发回退,绝不驱动二进制发布选择(见 package.json 与IS_RELEASE_BUILD)。
环境相关 effects
src/effects/app-config.ts 读取全部COMPOSIO_*环境变量;src/effects/toolkit-version-overrides.ts 解析COMPOSIO_TOOLKIT_VERSION_<NAME>=<ver>形式的覆盖,供代码生成时指定非 latest 的 toolkit 版本。
输出约定:可组合的 CLI 输出(stdout 只放数据)
遵循 Unix 惯例——人类可读装饰与机器可读数据分离:
- stdout——只放数据(
ui.output())。可被管道 /$(...)/> file捕获。 - stderr——放全部装饰(Clack spinner、日志、note、intro/outro)。终端可见,管道中不可见。
三个流是相互独立的契约,每个能力只依赖真正服务于它的流,刻意不存在聚合的 “interactive” 标志(见 src/services/terminal-ui.ts 的TerminalCapabilities):
- Prompting(
canPrompt)=stdin.isTTY && stderr.isTTY。stdin 必须能接收输入、stderr 必须能显示 Clack 提示。stdout 无关紧要:管道化数据绝不能改变提示或认证行为——composio login | tee与有人值守登录行为一致。 - 机器输出=
!stdout.isTTY。ui.output(data)仅在 stdout 被重定向(管道、子 shell、文件)或调用方传{ force: true }时写入。重定向 stdin 或 stderr 绝不能使数据泄漏到可见的 stdout 终端。 - Decoration(
canDecorate)=stderr.isTTY。spinner、日志、note 只需要 stderr,因此 stdin 或 stdout 被重定向时仍正常渲染。
规则清单
- 除
output()外的所有TerminalUI方法经 Clack 的{ output: process.stderr }写 stderr,且仅在 stderr 为 TTY(canDecorate)时渲染。 ui.output(data)仅在 stdout 被管道化(或显式force)时写 stdout。没有其他流参与该决策。- 提示(
ui.confirm、ui.select)仅在canPrompt时运行;否则不阻塞地回退到默认值(confirm 默认true,select 返回首个选项)。 - 管道化的 stdout 保持干净:
composio whoami | pbcopy只把 key 放进剪贴板——装饰仍在终端经 stderr 渲染,仅当 stderr 本身被捕获时才被抑制。 - 数据命令(whoami、version、login、generate 等)同时调用装饰(stderr)与
ui.output()(stdout)。 - 动作命令(logout、upgrade)不产生 stdout 数据——输出纯装饰。
- 绝不把数据写 stderr 或把装饰写 stdout,也绝不让程序行为(认证路径、命令流程)依赖 stdout 的 TTY 状态。
新增命令时的判断标准:“这个命令产生脚本应捕获的值吗?”——是 →ui.output(value)+ui.log.*/ui.note();否 → 仅装饰。
此外,cli-main.ts对显式请求的帮助(--help/-h)走 stdout,其余场景把框架自身的帮助/错误渲染经 Console 服务重定向到 stderr(log覆写为error),从而守住 “stdout 只放数据” 的契约。以version命令为例(src/commands/version.cmd.ts):普通模式同时调用ui.log.info(version)(stderr 装饰)与ui.output(version)(stdout 数据);--check模式输出结构化 JSON{current, latestStable, updateAvailable, checkStatus, lastChecked}到 stdout。
Effect.ts 模式与规范
生成器语法
全仓库统一使用生成器语法:
Effect.gen(function* () { const service = yield* ServiceName; // 解析依赖 const result = yield* someEffect; // 等待计算 yield* Effect.log('message'); return result; });关键模式:Effect.all([...], { concurrency: 'unbounded' })并行执行;Layer.provide()组合依赖;Effect.mapError()/Effect.catchTag()处理类型化错误;Effect.scoped做资源清理。
表驱动测试(独立有限选择的全组合)推荐用 Effect Array do 记法构建类型化笛卡尔积,而非枚举每种情况或嵌套循环:
const cases = pipe( Arr.Do, Arr.bind('firstAxis', () => choices), Arr.bind('secondAxis', () => choices) );每个Arr.bind为生成的用例增加一个独立轴。
Effect 安全与迁移接缝
- 绝不直接分支于 Effect 值内部的 tag 字段。使用所属模块的公开 refinement/matcher(
Option、Result、Exit、Cause、CliError)、Match.valueTags做穷尽联合匹配,或Predicate.isTagged做单个收窄守卫。 - 不要把普通
Error包进Effect.fail用于预期失败。为失败赋予有意义的Data.TaggedError类型(带结构化字段与保留的 cause),再用catchTag/catchTags恢复。Effect.die/Effect.dieMessage只留给不可能的不变量。 - 将
unknown、JSON、持久化状态、API 载荷视为信任边界。用effect/Schema解码或用Predicate收窄;as断言不是校验,手写结构守卫('x' in obj/typeof链)不能替代 schema。effect/Schema是 CLI 的 schema 工具——不要在 CLI 中引入 zod(zod 是 SDK 包与 docs 的约定)。 - 不要窥探
effect/unstable/cli的私有内部(parser 状态、HelpDoc字符串形状、CliError建议机制)。Command.runWith自行渲染帮助与解析/校验错误,命令树自省必须停留在公开的Command.Any表面(name、alias、subcommands)。CliError.InvalidValue接受结构化的{ option, value, expected, kind }字段而非自由文本消息——需要自定义校验消息的命令抛本地Data.TaggedError(如 src/commands/login.cmd.ts 的LoginOptionError),交给effect-errors美化打印,而非手写CliError。 - 优先
Effect.mapError、Effect.matchEffect与类型化恢复,而非把不同失败压平为单一消息错误的Effect.catch块(v4 中catchAll的新名称)。
Effect 边界策略(平台访问一律走服务)
node:path、node:fs、node:os、node:child_process、process.env、try/catch在src/中被 oxlint 禁止。合规替代:
| 需求 | 使用 |
|---|---|
| 路径运算(join/resolve/dirname/…) | effect/Path的Path服务(const path = yield* Path.Path) |
| 文件系统 I/O | effect/FileSystem的FileSystem服务(const fs = yield* FileSystem.FileSystem) |
| homedir / tmpdir / platform / arch | NodeOs服务(src/services/node-os.ts,唯一的node:os边界) |
| 子进程 | effect/unstable/process的ChildProcess/ChildProcessSpawner;比 CLI 存活更久的子进程经 src/services/detached-process.ts |
| 环境变量读取 | effect/Config |
同步易失败操作(JSON.parse、new URL、JSON.stringify) | Result.try+Data.TaggedError;JSON 记录经parseJsonRecord(src/utils/parse-json.ts) |
按子路径导入平台模块(import * as FileSystem from 'effect/FileSystem'、import * as BunFileSystem from '@effect/platform-bun/BunFileSystem'),绝不从@effect/platform-bun包桶导入;oxlint 在src/中拒绝包桶导入。
转换优先级:(1) 在现有 Effect 代码内 yield 服务;(2) 当调用方由 Effect 托管时把普通 helper 转换为 Effect(注意 v4 中Result不是Effect,不能直接 yield,须在Effect.gen内用Effect.fromResult(...)提升);(3) 把已解析的服务实例(如Path.Path、FileSystem.FileSystem)作为普通参数传入无法成为 Effect 的同步回调或 promise 管线(见tool-permissions.ts、generation/typescript/virtual-compiler-host.ts);(4) 自我提供 Layer 的模块在栈中加入BunPath.layer/BunFileSystem.layer/NodeOs.Default。
允许绕过服务的唯一代码位于声明的运行时边界:bin.ts引导、子进程伴生运行时(run-helpers-runtime.ts、run-subagent-*,打包为在用户派生进程中运行的.mjs)、导入时 UI 设置(ui/colors.ts、ui/redact.ts)、环境变量写入与全环境枚举(effect/Config无法表达)、以及父子composio run进程间的 spawn 时环境握手。每个此类边界都带内联// eslint-disable-next-line <rule> -- <reason>注释并登记在lint-boundaries.json。
强制执行:pnpm run validate:boundaries(属于pnpm test,CI 阻塞)在src/中的任何 eslint-disable 缺失于 manifest、缺少-- reason、或使用文件级形式时失败。不得新增 disable——应穿透服务。若代码确实无法在 Effect 运行时内运行,那是新边界:用pnpm run validate:boundaries -- --update重新生成 manifest 并在 PR 中说明边界理由。
代码生成管线:composio generate {ts,py}
composio generate的核心流程(src/generation):
- Fetch——拉取 toolkits、tools、trigger 类型(可用
--toolkits过滤)。 - Index——按 toolkit 前缀分组为
ToolkitIndex(见 src/generation/create-toolkit-index.ts)。工具与 trigger 类型按其 slug 前缀归属对应 toolkit;版本覆盖(versionMap,来自COMPOSIO_TOOLKIT_VERSION_<NAME>环境变量)仅对非 latest 版本生效。 - Generate——用
@composio/ts-builders的 AST builder 构建 TS/Python 源码(TypeScript 路径见 src/generation/typescript/generate.ts:支持emitSingleFile单文件与多文件两种输出,index 汇总文件为index.ts)。 - Transpile——可选地把 TS 转译为 ESM JS,供
@composio/core/generated使用。
--type-tools包含完整类型定义(withTypes: true路径,工具以带 slug 的完整Tool对象而非仅枚举名出现)。TS 生成依赖 JS compiler API(virtual-compiler-host.ts),这正是 TypeScript 依赖被固定在 TS6 的原因。
数据模型:Effect Schema
src/models 定义 Effect Schema 模型,配JSONTransformSchema()生成的fromJSON/toJSONhelper:Toolkit、Tool、TriggerType、UserData、Session。这些模型同时服务于磁盘持久化(如user_data.json的 schema 解码)与 API 载荷的解码,体现“把持久化状态与 API 载荷视为信任边界、用 schema 解码”的规范。
其他工程实践
客户端缓存同步
修改src/services/composio-clients.ts时,须在同一变更中检查composio-clients-cached.ts(见上文“缓存仓库与客户端同步”)。
CLI Demo 录制(VHS)
面向用户的 CLI 命令在改动文档化工作流、引入新可见命令面或需要发布说明 demo 覆盖时,应附带 VHS 录制(SVG + asciicast)。流程:
- 在
recordings/recordings.yaml添加条目(字段:name、command、description、sleepAfterEnter、长输出用height: dynamic)。 - 运行
bun scripts/record.ts——需要COMPOSIO_API_KEY且vhs在PATH上。
输出落在recordings/{tapes,svgs,ascii}/<group>/<name>.{tape,svg,ascii}。
发布工作流
- 推送
next分支并触碰 CLI 路径会自动发布滚动 beta。 - 常规 stable 路径通过
promote-stableworkflow action 把已测试的 beta 提升为 stable。 @composio/cli与@composio/cli-local-tools被 Changesets 忽略:永远不要为这两个包添加 changeset,否则会卡住 TypeScript SDK 发布 action。面向人的 CLI 变更直接写入CHANGELOG.md。package.json使用私有开发 sentinel(0.0.0-development),绝不是二进制发布权威。有意的 minor/major 发布应派发build-beta并带可选版本输入,验证该 beta 后正常 promote。- 关键工作流文件:
.github/workflows/build-cli-binaries.yml(二进制构建与发布)、.github/workflows/cli.test-installation.yml(发布后安装冒烟测试)、.github/scripts/cli-release/resolve-release-target.sh(beta/stable 目标解析)。
关键依赖速览
effect(固定4.0.0-rc.112;@effect/cli与@effect/platform不再是独立包,已折叠进effect的 barrel 与effect/unstable/{cli,http,process})、@effect/platform-bun、@effect/vitest(同款精确 pin)、@clack/prompts(终端 UI,默认写 stderr)、picocolors、@composio/client(Composio API)、@composio/core(类型)、@composio/ts-builders(AST 生成)、@composio/cli-keyring(OS 凭据存储)、@composio/cli-local-tools(本地 toolkit 定义)、@composio/json-schema-to-effect-schema、semver、open、extract-zip(完整清单见 ts/packages/cli/package.json)。
此外,仓库将 Effect 依赖源码以只读子模块固定在ts/vendor/effect/(effect@4.0.0-rc.112发布 commit),其中packages/effect/src/unstable/cli/、unstable/http/、unstable/process/与packages/platform/bun/src/是查阅 v4 API 行为的第一手参考;ts/vendor/effect/migration/提供官方 v3→v4 迁移指南。这使 CLI 的框架行为(如Command.runWith的渲染契约)可在仓库内直接溯源验证。
结语
@composio/cli展示了将 Effect 生态的服务化架构、类型化错误与结构化并发应用到 CLI 工程的完整范式:stdout/stderr独立契约保证脚本可组合性,Layer 依赖注入保证可测试性,schema 解码守住信任边界,边界策略把平台访问收拢到受控服务。无论你是要扩展该 CLI 的命令面、把项目迁移到 Effect v4,还是设计自己的现代 CLI,这份架构都可以作为直接参照——建议从 ts/packages/cli/src/bin.ts 与 ts/packages/cli/src/cli-main.ts 开始阅读,结合 ts/packages/cli/CLAUDE.md 与仓库根 AGENTS.md 快速建立全局认知。
【免费下载链接】composioComposio powers 1000+ toolkits, tool search, context management, authentication, and a sandboxed workbench to help you build AI agents that turn intent into action.项目地址: https://gitcode.com/GitHub_Trending/co/composio
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考