Doramagic 项目包 · 项目说明书
sanook-cli 项目
🪄 终端 AI 编程代理 —— BYOK,支持 12 家模型供应商、MCP 协议,并配备可跨会话持久记忆的第二大脑。使用 TypeScript 从零构建。
项目概述、快速开始与整体架构
sanook-cli 是一款「自带密钥(BYOK)的终端 AI 编程 agent」,使用 TypeScript 从零构建,作为 Claude Code 的替代品聚焦本地化、跨 session 记忆与模型可移植性。package.json 中的描述明确指出其覆盖 BYOK、9 家 LLM 提供方、MCP、cron 网关、技能系统与 Git 感知五大能力面。资料来源:packa...
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
一、项目定位与核心特性
sanook-cli 是一款「自带密钥(BYOK)的终端 AI 编程 agent」,使用 TypeScript 从零构建,作为 Claude Code 的替代品聚焦本地化、跨 session 记忆与模型可移植性。package.json 中的描述明确指出其覆盖 BYOK、9 家 LLM 提供方、MCP、cron 网关、技能系统与 Git 感知五大能力面。资料来源:package.json
核心特性可以归纳为四条主线:
- 多模型可移植:通过 Vercel AI SDK 抽象统一接入 Anthropic、Google、OpenAI、xAI、Mistral、Groq 等云端服务,并支持 Ollama / LM Studio 本地推理,以及将执行委托给
codexCLI 的子代理模式。资料来源:src/providers/registry.ts - 跨会话记忆:
sanook brain命令在本地生成 Obsidian vault 骨架,覆盖Projects/、Sessions/、Shared/、Intake/、Runbooks/、Skills/等目录,赋予 AI 长期记忆与知识管线。资料来源:second-brain/README.md - 本地 Web Dashboard:除终端 REPL 外,还内置 SSE 流式 Agent Console 与基于
ws + node-pty的可选 PTY Web Shell。资料来源:src/dashboard/terminal.ts - 插件与扩展:通过
skills/目录、mcp关键词以及可执行npm run eval的 eval 入口,支持技能系统、Model Context Protocol 与模型能力回归评测。资料来源:package.json
二、快速开始
1. 环境与安装
| 项目 | 要求 | 资料来源 |
|---|---|---|
| Node.js | >=22(engines.node 声明) | package.json |
| 命令入口 | sanook、sanookai → dist/bin.js | package.json |
| 推荐安装 | npm install -g sanook-cli 或 npx sanook-cli | src/dashboard/api-helpers.ts |
| 可选依赖 | node-pty、ws(用于 Dashboard Web Shell) | package.json |
| 开发运行 | npm run dev(tsx src/bin.ts) | package.json |
发布构建流程为:清理 dist/ → tsc -p tsconfig.build.json → 复制 dashboard 静态资源 → chmod 755 dist/bin.js,并通过 prepublishOnly 钩子强制在 npm publish 前重新构建。资料来源:package.json
2. 第一次交互
- 启动
sanook后,hasUsableEnvKey()会先校验环境变量里是否已经存在「可用」API key(含 OAuth/subscription token 拒绝策略)。无 key 或仅 OAuth 时引导用户进入首次运行向导。资料来源:src/providers/registry.ts - 在 REPL 中可通过
provider:model形式的 spec 切换模型,例如openai:gpt-5.5、anthropic:sonnet、groq:fast,canonicalSpec()在写入 UI 状态前会自动归一化。资料来源:src/providers/registry.ts - 开启 Dashboard 时,浏览器侧可访问
/api/terminal/run,前端通过 SSE 接收AgentEvent,并按sessionId在服务端保留ModelMessage[]多轮历史(最多 20 个会话)。资料来源:src/dashboard/terminal.ts
三、整体架构
sanook-cli 在概念上由四层组成:CLI 入口与参数解析 → Agent 循环 → 提供方适配层 → 持久化与扩展层。
flowchart TD
A[CLI 入口 dist/bin.js] --> B[首次运行向导 / 配置]
B --> C[REPL 主循环]
B --> D[Web Dashboard /api/terminal/run]
C --> E[Agent Loop /runAgent]
D --> E
E --> F[Provider 适配层 PROVIDERS]
F --> F1[Anthropic / Google / OpenAI / xAI / Mistral / Groq]
F --> F2[本地 Ollama / LM Studio]
F --> F3[Codex 子进程委托]
E --> G[Skills / MCP / 工具调用]
E --> H[Second-Brain Vault]
H --> I[Obsidian Shared/ + Sessions/]架构要点说明:
- Provider Registry 是单一事实源:新增厂商只需在
PROVIDERS表中追加一条ProviderConfig(含id / envVar / requiresKey / models / create()),循环与成本逻辑无需改动。资料来源:src/providers/registry.ts - Key 策略统一校验:
assertDirectApiKey()配合keyFormat正则会拦截sk-ant-oat*、ya29.*等 OAuth 凭据,避免使用 ChatGPT/Codex/Claude 订阅 token 触发 ToS 风险。资料来源:src/providers/registry.ts - 动态模型发现:
listModelsFor()针对 Google 走generativelanguage.googleapis.com,对 Anthropic 走x-api-key头,其他云端走/models端点,并通过AbortController限时避免挂起。资料来源:src/providers/models.ts - Codex 委托模式:
runCodex()通过codex exec启动非交互式子进程,解析 JSONL 事件并支持cwd隔离与resumeThreadId,兼容--json被工具激活时忽略的已知 bug。资料来源:src/providers/codex.ts - Dashboard 优雅降级:
shellStatus()会探测node-pty与ws是否同时可用,缺失时返回available: false并附带原因,UI 不会因此崩溃。资料来源:src/dashboard/terminal.ts
四、测试与质量保障
项目使用 Vitest 作为唯一测试框架,关键契约均有对应单测覆盖:
- Provider 注册表:验证 alias 解析(
gpt→openai:gpt-5.5)与canonicalSpec()在 UI 状态写入前的归一化行为,同时保证 OAuth 凭据在 embedder 路径上被降级为null。资料来源:src/providers/registry.test.ts - Dashboard 元数据:确认
npm是唯一ready=true且被推荐的安装方式,curl / homebrew / winget都标注为尚未就绪并附带部署原因。资料来源:src/dashboard/api-helpers.test.ts - Eval 模型解析:
evalModelFromEnv()会对SANOOK_MODEL去空白,缺省回退到sonnet,与npm run eval(tsx src/eval/run.ts)形成闭环。资料来源:src/eval/run.test.ts · package.json
发布前可执行 npm run typecheck 保证 TypeScript 干净,再跑 npm test 验证关键不变量。
另请参阅
second-brain/README.md— Obsidian vault 模板与 AI Routing Contractsrc/providers/registry.ts— Provider 注册表与 Key Policy 详细说明src/dashboard/terminal.ts— Dashboard Agent Console 与 Web Shell 行为细节package.json— scripts、bin、files、keywords 的完整定义
来源:https://github.com/Sir-chawakorn/sanook-cli / 项目说明书
代理循环、工具沙箱与模型提供商
sanook-cli 是一个 BYOK(自带密钥)的终端 AI 编程代理,本页聚焦其三大核心机制:代理循环(agent loop)、工具沙箱与审批、多模型提供商注册表。三者通过 runAgent 入口协同:循环驱动模型推理,模型返回的 toolcall 被沙箱拦截,审批通过后落地执行,结果再回到循环中继续。
继续阅读本节完整说明和来源证据。
整体架构与事件流
代理循环是整个系统的"心脏"。仪表板后端把 REPL 的体验复刻到了 Web 端,证据见 src/dashboard/terminal.ts:它显式导入 runAgent, type AgentEvent 并把代理事件以 SSE 形式流式转发给浏览器,包括文本、推理、工具调用、🧠 记忆事实以及 ✨ 自动生成的技能 资料来源:src/dashboard/terminal.ts:1-12。每个浏览器会话在后端维护独立的 ModelMessage[] 历史,上限 20 个并发会话 资料来源:src/dashboard/terminal.ts:5-8。
flowchart LR
A[用户输入] --> B[runAgent<br/>src/loop.ts]
B --> C{模型提供商<br/>registry.ts}
C -- text/reasoning --> D[事件流 SSE]
C -- tool_call --> E[沙箱校验<br/>sandbox.ts]
E --> F{需审批?<br/>approval.ts}
F -- 是 --> G[checkpoint<br/>回滚锚点]
F -- 否 --> H[执行工具]
H --> I[结果回灌<br/>agentContext.ts]
I --> B
D --> J[REPL / Web 终端]
G --> H工具沙箱、审批与检查点
任何模型发起的工具调用都必须穿越沙箱和审批两道关卡。src/sandbox.ts 负责把文件系统与命令执行约束在工作区范围内;src/approval.ts 决定该调用是否需要人类确认(写操作、对外网络、危险命令通常需要)。一旦执行开始,src/checkpoint.ts 记录回滚锚点——若后续步骤失败或用户拒绝,可以从锚点恢复。src/agentContext.ts 则把工具结果、记忆、技能等"上下文增量"累积起来,供下一轮循环使用。当上下文接近模型窗口上限时,src/compaction.ts 触发摘要压缩,保留关键事实与最近消息。
模型提供商注册表
src/providers/registry.ts 是多模型支持的"单一事实源"。它导出一个 PROVIDERS 表,每个条目描述一家提供商的鉴权方式、基础 URL、支持的模型别名以及工厂函数 资料来源:src/providers/registry.ts:1-25。模型规范(spec)支持三种写法:provider:model、provider:alias、或裸别名(如 gpt、haiku、sonnet),parseSpec 与 canonicalSpec 把它们规范化为 provider:model-id 资料来源:src/providers/registry.ts:79-96。
提供商分两类:直接 API(如 anthropic、openai、xai、mistral、groq)和委托型 codex,后者不持有 key,而是依赖本地 codex CLI 的登录状态 资料来源:src/providers/codex.ts:1-25。hasUsableEnvKey 会拒绝 OAuth/订阅型 token,避免把 ChatGPT 订阅 key 误当作 API key 使用 资料来源:src/providers/registry.ts:107-119。
fastSibling(spec) 为循环内的"轻量任务"(摘要、压缩)选择同家的快速模型——比如 anthropic 自动落到 haiku、google 落到 flash——无快档则原样返回 资料来源:src/providers/registry.ts:6-13。当用户希望使用"非别名"的新模型时,可通过 provider:full-id 直接覆盖 资料来源:src/providers/registry.ts:18-25。
远程模型发现与评估回路
src/providers/models.ts 的 listRemoteModels 直接调用各家 /models 端点,把权威模型 ID 拉回本地——google 用 query key、anthropic 用 x-api-key、OpenAI 兼容用 Bearer,失败/超时/本地模型则返回 [],由调用方回退到 curated 别名 资料来源:src/providers/models.ts:1-25。评估脚本读取 SANOOK_MODEL 环境变量,trim 后空白则回退到 sonnet 资料来源:src/eval/run.test.ts:1-10,确保离线评估永远有可用的目标模型。
常见失败模式
- OAuth key 误用:将
sk-ant-oat…之类的订阅 token 设为ANTHROPIC_API_KEY时,assertDirectApiKey抛错并提示去控制台取真 key 资料来源:src/providers/registry.ts:112-118。 - 不支持的提供商:解析到未知 provider 时,错误信息列出所有受支持的 provider 名称 资料来源:src/providers/registry.ts:55-60。
- Codex 未登录:委托型 provider 需要
codex login,否则runCodex给出明确安装/登录指引 资料来源:src/providers/codex.ts:6-20。 - SSE 连接断开:
sseSend会检测res.destroyed/writableEnded,避免向已关闭的 socket 写入 资料来源:src/dashboard/terminal.ts:9-15。
See Also
来源:https://github.com/Sir-chawakorn/sanook-cli / 项目说明书
分层记忆系统与第二大脑工作区
sanook-cli 是一个面向终端的 AI 编程 agent,主打"BYOK(自带密钥)+跨会话记忆"两大能力。其记忆体系由两层组成:运行时分层记忆(短/长期事实、回合检索)与第二大脑工作区(Obsidian 风格的知识库脚手架)。两者协同工作,使 agent 在不同会话之间能保留上下文,并将对话成果沉淀为可被人类检索的结构化笔记。
继续阅读本节完整说明和来源证据。
概述
sanook-cli 是一个面向终端的 AI 编程 agent,主打"BYOK(自带密钥)+跨会话记忆"两大能力。其记忆体系由两层组成:运行时分层记忆(短/长期事实、回合检索)与第二大脑工作区(Obsidian 风格的知识库脚手架)。两者协同工作,使 agent 在不同会话之间能保留上下文,并将对话成果沉淀为可被人类检索的结构化笔记。
package.json 的关键字同时列出 cross-session-memory、second-brain、obsidian,且将 second-brain/ 目录随 npm 包一并发布,说明该项目将"长期记忆"作为一等公民功能交付。资料来源:package.json
来源:https://github.com/Sir-chawakorn/sanook-cli / 项目说明书
网关、消息通道、MCP、技能与本地面板
sanook-cli 是一个 BYOK(Bring Your Own Key)的终端 AI 编程代理。它通过统一的"提供商注册表"将 9 家云端/本地 LLM 厂商接入同一个 agent 循环,再借由本地面板(dashboard)把这些能力暴露成 HTTP/SSE/WebSocket 端点,并允许子进程级"委托代理"(例如 codex CLI)作为另一种消息通道。本页汇总这...
继续阅读本节完整说明和来源证据。
sanook-cli 是一个 BYOK(Bring Your Own Key)的终端 AI 编程代理。它通过统一的"提供商注册表"将 9 家云端/本地 LLM 厂商接入同一个 agent 循环,再借由本地面板(dashboard)把这些能力暴露成 HTTP/SSE/WebSocket 端点,并允许子进程级"委托代理"(例如 codex CLI)作为另一种消息通道。本页汇总这几条通路的设计、配置与典型用法。
1. 架构总览
flowchart LR
U[用户 / REPL] --> DASH[本地面板<br/>src/dashboard/terminal.ts]
DASH -->|POST /api/terminal/run (SSE)| LOOP[agent loop<br/>runAgent]
DASH -->|ws /api/terminal/shell| PTY[node-pty<br/>可选依赖]
LOOP --> REG[提供商注册表<br/>src/providers/registry.ts]
REG -->|sdk| SDK[Vercel AI SDK<br/>anthropic/google/openai/xai/mistral/groq]
REG -->|delegate| CODEX[codex subprocess<br/>src/providers/codex.ts]
SDK --> REMOTE[远端 /models 枚举<br/>src/providers/models.ts]
REG --> SB[second-brain 记忆库<br/>second-brain/README.md]上图中"网关"由 dashboard 的 HTTP/SSE 入口充当;"消息通道"由 PROVIDERS 表覆盖的 9 个厂商与 codex 子进程提供;"技能"与"本地面板"分别通过 skills/ 目录(打包到 npm,见 package.json)和 src/dashboard/* 实现。资料来源:src/dashboard/terminal.ts、src/providers/registry.ts。
2. 提供商注册表:消息通道的核心
src/providers/registry.ts 维护一个 PROVIDERS 表,每条记录声明 envVar、baseURL、requiresKey、keyFormat(用正则拒绝 OAuth/subscription 凭证)、models(alias → 真实 model id 的映射)以及 create(key, baseURL) 工厂。新增厂商只需在表内增加一项,循环、计费、密钥策略不需改动。资料来源:src/providers/registry.ts。
parseSpec(spec)解析"provider:model"、"provider:alias"、裸别名或裸 model id(默认 provider 为anthropic)。canonicalSpec(spec)在写入 REPL 状态前把别名归一为provider:model-id,避免状态机里残留别名。fastSibling(spec)返回同一 provider 的fast/flash/haiku/air兄弟型号,给 summarization、压缩等机械性任务省成本。hasUsableEnvKey(provider)既要看环境变量里有没有 key,还要跑一遍assertDirectApiKey,确保不是sk-ant-oat…这类被 Anthropic/Google 禁止的 OAuth 复用 token。consoleUrl(provider)在错误信息/wizard 里直接给出去 console 拿 key 的 URL。
kind: 'sdk' | 'delegate' 字段区分"走 Vercel AI SDK"和"spawn 子进程 agent",目前 codex 是唯一的 delegate 通道——它不查 /models,而是由 src/providers/codex.ts 的 codexCheck() 验证 CLI 安装与 codex login 状态。
3. 本地面板:SSE 通道与可选 PTY
src/dashboard/terminal.ts 实现了浏览器端的两种终端后端:
- Agent console:
POST /api/terminal/run接收 prompt,直接复用runAgent并通过 SSE 转发text/reasoning/tool事件,包含 🧠 remember 事实与 ✨ 自动创建的技能——与 REPL 完全一致。多轮历史在服务端按sessionId维护,最长 20 个 session,写入前会用sseSend()检查 socket 是否已销毁。 - Raw shell:
ws://…/api/terminal/shell在node-pty与ws两个可选依赖都装好时升级为真实 PTY;否则 UI 降级。shellStatus()报告当前可用性。
由于 node-pty 与 ws 在 package.json 中被声明为 optionalDependencies,缺少它们不会阻断 npm install,但本地面板会回退到纯 agent 通道。安装方式上,dashboardInstall() 暴露的 npm/npx 是当前唯一 ready: true 的方法,curl/irm 脚本需等 sanook.ai 域名与发布基础设施就绪。资料来源:src/dashboard/api-helpers.ts。
4. 远端模型枚举与 Codex 委托
src/providers/models.ts 的 listRemoteModels() 直接拉取 provider 的 GET /models,按厂商返回三种不同 shape:
| 厂商 | 鉴权头 | 列表字段 |
|---|---|---|
?key=… query | models[].name(带 supportedGenerationMethods 过滤) | |
| Anthropic | x-api-key + anthropic-version | data[].id |
| OpenAI 兼容 | Authorization: Bearer … | data[].id |
mergeModelOptions() 把别名按真实 model id 分组后展平成 ModelOption[],避免 React key 冲突(出现"两条选项对应同一个 model"这类 bug)。失败/超时/本地/无端点时返回 [],调用方会回退到 curated alias。
src/providers/codex.ts 的 runCodex() 通过 stdin 投递 prompt 并解析 JSONL 事件(text/usage/thread),对 codex bug #15451(--json 在启用 tools 时被忽略)做容错。可选的 cwd 让父 agent 把 codex 隔离到 worktree 子目录中。
5. 安装、引擎与打包
package.json 声明 bin 字段同时提供 sanook 与 sanookai 两条命令,都指向 dist/bin.js;engines.node 强制 >=22;build 脚本先清空 dist/、跑 tsc -p tsconfig.build.json、再执行 scripts/copy-dashboard-static.mjs 把静态资源复制进 dist、最后 chmod 0o755。发布包额外携带 skills/、second-brain/、scripts/postinstall.mjs、.env.example,让 sanook brain 一键 scaffold 出一个 Obsidian vault(见 second-brain/README.md)作为跨 session 的"第二大脑"。
常见失败模式
- OAuth token 被识别为直接 API key:
ANTHROPIC_API_KEY=sk-ant-oat…会被assertDirectApiKey拒绝,hasUsableEnvKey()返回false,wizard 会强制进入而不是误判"已就绪"。 - 可选依赖缺失导致 PTY 不可用:
shellStatus()会报告ready: false,浏览器自动回退到 agent console;不影响主路径。 - codex 未登录:
codexCheck()返回{ installed: true, loggedIn: false, reason: 'ยังไม่ได้ login — รัน: codex login' },调度层会跳过而非崩溃。 - Node.js 版本过低:
<22会直接被engines阻拦npm install。
See Also
- 提供商与模型路由
- 本地面板与 Web 终端
- Second Brain 记忆库
- Codex 委托代理
来源:https://github.com/Sir-chawakorn/sanook-cli / 项目说明书
失败模式与踩坑日记
保留 Doramagic 在发现、验证和编译中沉淀的项目专属风险,不把社区讨论只当作装饰信息。
安装可能改变本机 AI 工具行为,用户需要知道写入位置和回滚方法。
假设不成立时,用户拿不到承诺的能力。
新项目、停更项目和活跃项目会被混在一起,推荐信任度下降。
风险会影响是否适合普通用户安装。
Pitfall Log / 踩坑日志
项目:Sir-chawakorn/sanook-cli
摘要:发现 7 个潜在踩坑项,其中 0 个为 high/blocking;最高优先级:配置坑 - 可能修改宿主 AI 配置。
1. 配置坑 · 可能修改宿主 AI 配置
- 严重度:medium
- 证据强度:source_linked
- 发现:项目面向 Claude/Cursor/Codex/Gemini/OpenCode 等宿主,或安装命令涉及用户配置目录。
- 对用户的影响:安装可能改变本机 AI 工具行为,用户需要知道写入位置和回滚方法。
- 证据:capability.host_targets | https://github.com/Sir-chawakorn/sanook-cli | host_targets=mcp_host, claude, claude_code, gemini_cli, codex
2. 能力坑 · 能力判断依赖假设
- 严重度:medium
- 证据强度:source_linked
- 发现:README/documentation is current enough for a first validation pass.
- 对用户的影响:假设不成立时,用户拿不到承诺的能力。
- 证据:capability.assumptions | https://github.com/Sir-chawakorn/sanook-cli | README/documentation is current enough for a first validation pass.
3. 维护坑 · 维护活跃度未知
- 严重度:medium
- 证据强度:source_linked
- 发现:未记录 last_activity_observed。
- 对用户的影响:新项目、停更项目和活跃项目会被混在一起,推荐信任度下降。
- 证据:evidence.maintainer_signals | https://github.com/Sir-chawakorn/sanook-cli | last_activity_observed missing
- 严重度:medium
- 证据强度:source_linked
- 发现:no_demo
- 证据:downstream_validation.risk_items | https://github.com/Sir-chawakorn/sanook-cli | no_demo; severity=medium
5. 安全/权限坑 · 存在评分风险
- 严重度:medium
- 证据强度:source_linked
- 发现:no_demo
- 对用户的影响:风险会影响是否适合普通用户安装。
- 证据:risks.scoring_risks | https://github.com/Sir-chawakorn/sanook-cli | no_demo; severity=medium
6. 维护坑 · issue/PR 响应质量未知
- 严重度:low
- 证据强度:source_linked
- 发现:issue_or_pr_quality=unknown。
- 对用户的影响:用户无法判断遇到问题后是否有人维护。
- 证据:evidence.maintainer_signals | https://github.com/Sir-chawakorn/sanook-cli | issue_or_pr_quality=unknown
7. 维护坑 · 发布节奏不明确
- 严重度:low
- 证据强度:source_linked
- 发现:release_recency=unknown。
- 对用户的影响:安装命令和文档可能落后于代码,用户踩坑概率升高。
- 证据:evidence.maintainer_signals | https://github.com/Sir-chawakorn/sanook-cli | release_recency=unknown
来源:Doramagic 发现、验证与编译记录