mycode-agent
v0.2.1
Published
mycode — terminal coding agent kernel (event-driven, four-layer architecture, Anthropic Messages protocol)
Maintainers
Readme
mycode
终端代码智能体内核 —— 按 spec/(SPEC-00 ~ SPEC-10)实现。TypeScript + Node.js ≥ 20,
事件驱动、四层架构、全量中间结果落盘(journal 为唯一事实来源)。
架构
L5 入口层 CLI(参数/配置/组合根/--print) TUI(Ink + React) spec/06, 07
L4 Agent Loop 用户输入 → 模型推理 ⇄ 工具执行 → 最终答案 spec/05
L3+ 扩展 MCP 客户端(stdio) / Skills —— Claude Code 兼容 spec/08, 09
横切 Hooks 六事件生命周期钩子 —— Claude Code 兼容契约 spec/10
L3 工具层 注册 / 执行 / 权限 / 路径安全(6 个内置工具) spec/04
L2 会话层 消息历史 / 持久化 / 恢复 / 上下文裁剪 spec/03
L1 模型底座 Anthropic Messages 流式适配 / 重试 / 规范化 spec/02
L0 事件系统 总线 + 追加式 journal + 重放(横切所有层) spec/01安装与快速开始
# 方式一:npm 安装(发布后)。包名 mycode-agent,命令名是 mycode
npm install -g mycode-agent
# 方式二:从本仓库本地安装(立即可用);也可先 npm pack 再装生成的 tgz
npm install -g .
# 密钥只经环境变量;端点/模型在 .mycode/settings.json 里覆盖
export ANTHROPIC_API_KEY=sk-...
# 非交互:单次任务,stdout 只有最终答案,可管道化
mycode -p "读 README 并总结"
# 交互 TUI(需 TTY,≥ 80×24)
mycode # 新会话
mycode -c # 恢复本项目最近会话
mycode -s <session_id>配置第三方 Anthropic 兼容端点(如 GLM):在项目 .mycode/config.json 里覆盖
providers.anthropic.base_url 与 model(思考型模型建议 max_tokens ≥ 32768,见文末实现说明)。
发布:npm publish(prepack 会自动 build + test;本机需先 npm login)。
--print 模式下 ask 权限默认拒绝(模型会收到 ERROR: permission denied 并改道),
--yolo 视为允许;bash 硬拒绝清单(rm -rf /、fork 炸弹、裸设备、chmod -R 777 /)
在任何模式下都不可放宽。
权限模式(TUI 内随时切换)
| 模式 | 行为 |
|---|---|
| default | 按策略表逐次判定 / 弹层询问 |
| acceptEdits | write_file / edit_file 自动放行,其余照旧 |
| plan | 只读规划:read/grep/glob/Skill 可用,其余一律拒绝(模型会收到 plan mode is read-only) |
| bypassPermissions | 全部放行(硬拒绝清单仍然生效) |
切换:Shift+Tab 循环,或 /mode [name](大小写不敏感);状态栏左下角显示模式名
(大写、纯文字色:DEFAULT 灰 / ACCEPT_EDITS 青 / PLAN 品红 / BYPASS 红加粗)。
模式为进程级,对所有 Run 生效直到再次切换;--print --yolo 等价于 bypassPermissions。
转录显示(v0.13)
- 工具调用折叠:一次运行里的连续工具调用收敛为一行摘要
● 6 次调用 · bash ×3 · read_file ×2 · edit_file ✓;单次调用保留参数卡片● bash(ls -la) ✓;不显示耗时;失败调用仍逐条给出原因。运行中实时显示当前 工具卡片,运行结束才折叠定型(resume 回放同样折叠)。 - AI 输出 Markdown 渲染:标题(粗体亮蓝)、
**加粗**、`行内代码`(青色)、 围栏代码块(┌─/│/└─灰色边栏)、无序列表(•)、引用、分隔线、表格分隔行; 纯文字配色、无背景块。流式过程中按行动态渲染(半行未闭合标记属正常)。 @文件引用(v0.14):输入@弹出工作区文件/目录列表(尊重 .gitignore,2s 走查缓存),继续输入按 文件名 > 路径 前缀/子序列排序过滤;↑↓ 选择、Tab/回车插入、 Esc 关闭;选中目录插入@dir/后继续深入下一级。提交时消息里的@路径自动把 文件内容(≤16K 字符/文件,二进制跳过)或目录列表作为附加上下文注入 system prompt。- 权限确认为可选列表:不再只靠字母 —
❯ 允许 / 拒绝 / 本 run 内总是允许↑↓ 选择、Enter 确认;y/n/a 快捷键与 Esc 拒绝保留。
会话 ID 与 OpenTelemetry 观测(v0.2.1)
- 会话 ID 为 UUID(Claude Code 风格,
crypto.randomUUID),状态栏显示前 8 位十六进制;mycode -s <id>支持短前缀匹配;旧格式目录(sess-<words>/sess_<ULID>)仍可列出与恢复。 - OTel 遥测(零依赖,与 Claude Code 的开关兼容):
指标(cumulative):export CLAUDE_CODE_ENABLE_TELEMETRY=1 # 或 MYCODE_ENABLE_TELEMETRY=1 export OTEL_METRICS_EXPORTER=otlp # otlp | prometheus | console(默认 console) export OTEL_EXPORTER_OTLP_ENDPOINT=http://collector:4318 # otlp 用(OTLP/HTTP JSON) # export OTEL_PROMETHEUS_PORT=9464 # prometheus 用,GET /metrics # export OTEL_METRICS_INTERVAL=60000 # 刷新间隔 ms(默认 60s)mycode.token.usage{type=input|output,model,session_id}、mycode.api_request.duration{model,status}(直方图)、mycode.tool.usage{tool_name,status}、mycode.active.time{session_id};退出时最终 flush。/status与/doctor显示遥测状态。
扩展机制(配置方式与 Claude Code 一致)
MCP server(stdio 传输;同名项目级覆盖用户级;.mycode/config.json 的 mcp.disabled 可剔除):
| 来源 | 文件 |
|---|---|
| 用户级(Claude Code 兼容) | ~/.claude.json 的 mcpServers 字段 |
| 用户级(mycode 原生) | ~/.mycode/mcp.json |
| 项目级(Claude Code 兼容) | <project>/.mcp.json |
| 项目级(mycode 原生) | <project>/.mycode/mcp.json |
{ "mcpServers": { "calc": { "command": "node", "args": ["calc-server.mjs"], "env": { "KEY": "${VAR}" } } } }工具以 mcp__<server>__<tool> 命名注册,默认权限 ask;command/args/env/cwd 支持 ${VAR} 与 ${VAR:-default} 展开。mycode mcp list 查看状态与工具数。
Skills(SKILL.md + frontmatter name/description;同名项目覆盖用户;调用时热读取):
<project>/.claude/skills/<name>/SKILL.md ~/.claude/skills/<name>/SKILL.md
<project>/.mycode/skills/<name>/SKILL.md ~/.mycode/skills/<name>/SKILL.md模型通过内置 Skill 工具按名加载技能正文(渐进式披露),权限 allow,未知名返回可用清单。
自定义命令(Claude Code commands 兼容,<name>.md,四目录发现,同名 project 覆盖 user,内置名不可覆盖):
<project>/.claude/commands/<name>.md ~/.claude/commands/<name>.md
<project>/.mycode/commands/<name>.md ~/.mycode/commands/<name>.md---
description: 部署前端到指定环境
argument-hint: [env]
allowed-tools: bash, read_file
---
请把前端部署到 $ARGUMENTS 环境……TUI 中 /name args… 调用:$ARGUMENTS / $1..$9 替换后作为提示词提交;子目录命名空间
(frontend/component.md → /frontend:component);allowed-tools 为该次 Run 的工具白名单。
内置命令:/help /clear /sessions /model /mode /display /status /cost /permissions
/compact(LLM 压缩上下文,历史折叠为摘要消息)/mcp /doctor /review(审查 git diff)
/init(生成 AGENTS.md 并自动附加到 system prompt)/usage /tools /agents /exit /quit。
Hooks(stdin 喂入 Claude Code 兼容 payload:session_id/transcript_path/cwd/hook_event_name/tool_name/tool_input/prompt 等;matcher 支持 Bash→bash 等别名与 |、glob):
| 事件 | 语义 |
|---|---|
| UserPromptSubmit | stdout 注入本 run 的 system 上下文;exit 2 拒绝输入 |
| PreToolUse | exit 2 或 JSON permissionDecision: deny 阻断(stderr 回传模型);allow 跳过权限询问 |
| PostToolUse | 副作用钩子(如审计),收到 tool_response.output |
| Stop | exit 2 或 JSON decision: block 则回灌 [stop-hook] 理由继续(每 run ≤3 次) |
| SessionStart / SessionEnd | 会话生命周期(startup / resume / clear / end) |
{ "hooks": { "PreToolUse": [ { "matcher": "bash|Bash", "hooks": [ { "type": "command", "command": "./guard.sh", "timeout": 30 } ] } ] } }发现顺序:~/.claude/settings.json < .claude/settings.json < .claude/settings.local.json < ~/.mycode/settings.json < .mycode/config.json(弃用) < .mycode/settings.json < .mycode/settings.local.json。
每次 hook 执行落 durable 事件 hook.executed(含 blocked/reason,可审计)。
Subagents(.md 定义 + frontmatter,四目录发现,同名 project 覆盖 user;正文 = 子代理 system prompt):
<project>/.claude/agents/<name>.md ~/.claude/agents/<name>.md
<project>/.mycode/agents/<name>.md ~/.mycode/agents/<name>.md---
name: code-auditor
description: 代码审计员。需要统计代码规模、检查代码质量时使用。
tools: read_file, glob, grep # 可选白名单(缺省继承除 Task 外全部)
model: glm-4.6 # 可选模型覆盖
---
(正文 = 子代理 system prompt)存在定义时注册内置 Task 工具(默认权限 ask):模型派 Task(subagent_type, prompt)
(缺省按 description 关键词路由)→ 子代理在独立上下文中跑自己的模型⇄工具循环
(轮数上限 limits.subagent_max_turns,默认 20;v1 不可嵌套派生)→ 最终报告作为工具
结果回到父对话。子循环事件全部落 journal(agent.started / completed / aborted + 带
run_1.agent_1 标识的 model/tool 事件),用量归并入 usage_total,父会话历史零污染;
TUI 中渲染为 ◆ agent:<name> 卡片,/agents 可列出全部定义。
配置(后者覆盖前者)
- 内建默认值
~/.mycode/config.json(已弃用,兼容读取并告警)~/.mycode/settings.json(用户级)<project>/.mycode/config.json(已弃用,兼容读取并告警)<project>/.mycode/settings.json(项目级)<project>/.mycode/settings.local.json(项目本地级,建议加入 .gitignore)- 环境变量
MYCODE_PROVIDER/MYCODE_MODEL - CLI
--provider/--model
文件命名与层级对齐 Claude Code 的 settings 惯例;同名弃用文件 config.json 永远低于同级
settings.json。密钥只经环境变量(api_key_env 指定变量名);配置文件里出现 api_key
之类的明文密钥键会被拒绝加载。hooks 键写在 settings 文件里(发现层级见 SPEC-10 §2)。
// <project>/.mycode/settings.json 示例
{
"limits": {
"max_turns": 40,
"autocompact_threshold": 0.8 // 上下文占用 ≥ 预算 80% 时自动 /compact(0 关闭)
},
"memory": {
"dream_on_exit": true, // 退出时自动“做梦”:把本会话蒸馏成长期记忆
"max_chars": 6000
}
}高级能力(v0.11)
- Auto-compact:每次运行前估算上下文占用,越过
limits.autocompact_threshold(默认 0.8,即消息预算的 80%)自动 LLM 压缩为摘要,不再静默丢弃旧消息、也不再 中途context_overflow。session.compacted事件在任意显示模式下都会提示。 - 长期记忆 + Dreaming:两层 Markdown 记忆文件——
~/.mycode/memory/MEMORY.md(全局) 与<project>/.mycode/memory/MEMORY.md(项目),每次请求注入 system prompt(封顶)。/memory add [-g] <text>手动写入;/dream用一次小预算 LLM 调用从当前会话蒸馏 「值得跨会话记住的东西」(用户偏好/项目事实/踩坑),去重后写入记忆;dream_on_exit开启时(默认开)退出自动做一次(后台代理跳过,其 worktree 记忆会被丢弃)。 /insights(CLI:mycode insights):跨全部会话 journal 的使用分析——token 总量、 按日柱状趋势、工具调用成功率/耗时、Top 会话、失败热点。/loop [Nx] <prompt>:自主迭代。带Nx时固定跑 N 轮(上一轮结果喂给下一轮); 不带时由严格的 LLM judge 每轮判定DONE/CONTINUE,CONTINUE 附带批评作为下一轮输入。/goal <description>:目标驱动模式——agent 每轮推进目标并给出验证证据,judge 判定目标完全达成才停(上限 15 轮,Ctrl+C 随时中断)。循环运行时状态栏显示loop i/n。- 后台会话 + worktree 隔离:
/bg [--no-wt] <prompt>派出一个 detached 的mycode -p --yolo子进程,git 仓库下自动git worktree add(分支mycode/bg/<id>, 目录~/.mycode/worktrees/)——与前台会话文件级隔离,退出 mycode 也会继续跑。 注册表~/.mycode/agents/registry.json;/agents列表 //agents <id>详情 (日志尾部 + worktree 改动 + 合并命令)//agents clean清理记录;完成/失败每 5s 自动提醒一次;CLImycode agents [clean]同样可用。非 git 目录回退原目录运行(会告警)。
运行数据
.mycode/sessions/<sess-id>/events.jsonl # journal(唯一事实来源,append-only)
.mycode/sessions/<sess-id>/blobs/ # 超限大负载(sha256 内容寻址)
~/.mycode/memory/MEMORY.md # 全局长期记忆(/dream、/memory add)
<project>/.mycode/memory/MEMORY.md # 项目长期记忆
~/.mycode/agents/registry.json # 后台代理注册表(/bg、/agents)
~/.mycode/agents/logs/<id>.log # 后台代理完整输出
~/.mycode/worktrees/<repo>-<id>/ # 后台代理的 git worktree同一会话目录同时只允许一个进程写入(目录锁 + 崩溃残留自动恢复); journal 尾部残缺行在加载时截断,seq 跳号视为损坏直接报错。
开发
npm test # 94 个用例:各层单测 + mock 端点的 --print 端到端(含 MCP/Skills/Hooks/Subagent e2e)
npm run typecheck
npm run build测试不需要真实 API Key:模型层用注入的 fetch mock,端到端用本地 SSE 服务器。
实现说明(与 spec 的澄清 / 已知限制)
model.request.started为 durable 事件。SPEC-01 §3.5 规定 volatile 全集只有两个model.stream.*增量事件,SPEC-05 §8 示例中把model.request.started标注在 volatile 行存在笔误;以 SPEC-01(事件目录的唯一权威)为准,该事件落盘并占用 seq。- 重放驱动的分层:SPEC-01 §7 的
replay(journal): SessionState需要会话层的 fold 与状态类型;为满足「下层不得 import 上层」,events 层提供通用replayEvents(journal, fold, initial),session 层用自己的 fold 包装,两条路径共用 同一 fold 实现(SPEC-03 §4 的要求不受影响)。 - TUI 鼠标滚轮未实现(Ink 5 不透出鼠标事件);滚动由 PgUp/PgDn、Shift+↑/↓、 Home/End 覆盖(Home/End 依赖终端上报,Ink 的 Key 类型未声明,已做兼容探测)。
- 多字符输入拆分:Ink 只在单字符 chunk 中识别回车/控制键;粘贴多行文本或驱动 一次写入多个字节时,TUI 侧自行拆分为「可打印串 + 单控制键」再分发。
- 进程退出:TUI/Ink 卸载后可能残留被引用的句柄(stdin 监听等),入口在清理完成后
显式
process.exit;--print路径先等待 stdout 冲刷回调再退出,保证管道输出完整。 - v1 平台:bash 工具固定
/bin/sh -c+ 独立进程组(超时杀整组),Unix only。 - GLM / BigModel Anthropic 兼容端点实测要点(2026-09 实战验证):
base_url = https://open.bigmodel.cn/api/anthropic,模型如glm-4.6;- 该端点默认输出 Anthropic 风格
thinking块(适配器按规忽略未知块类型,不回传也不报错, 已实测 10+ 轮 tool_use 往返无碍)。思考消耗输出预算:max_tokens过小(如 8192)时 会出现stop_reason=max_tokens且正文为空,建议 thinking 模型配max_tokens ≥ 32768, 或使用端点支持的thinking: {"type":"enabled","budget_tokens":N}封顶(v2 可做成配置项); input_tokens在最终message_delta.usage中才给出真实值(message_start 为 0), 适配器已兼容(取两处较大值),官方端点行为不变。
v1 非目标(v2 方向)
子代理嵌套派生、OpenAI 兼容适配器、工具并行、会话级权限豁免、MCP HTTP/SSE 传输、 hooks 的 Notification/PreCompact 事件、跨后台代理消息传递(SendMessage)等 —— 见 SPEC-00 §1.2。 (v0.11 已提前落地:上下文 LLM 压缩 + 自动触发、TUI 内会话切换、长期记忆/Dreaming、 insights、/loop 与 /goal 自主迭代、后台会话 + worktree 隔离。)
