基于 AI SDK 的命令行 Agent 框架,支持工具调用、可后台运行的 Shell 长任务、Plan Mode、Task V2 持久化任务图、上下文自动压缩、会话持久化、@file 文件引用、跨对话项目记忆、Skills 渐进式披露、后台 SubAgent、Worktree 隔离、Agent Teams 多智能体协作和 MCP 扩展。
| 层面 | 技术 |
|---|---|
| 运行时 | Node.js ≥ 22 + TypeScript |
| AI SDK | ai (Vercel AI SDK) + @ai-sdk/openai |
| MCP 协议 | @modelcontextprotocol/sdk |
| 包管理 | pnpm / npm |
| 运行方式 | npm CLI 包 |
- Node.js ≥ 22
- npm、pnpm 或其他兼容 npm registry 的包管理器
外部用户推荐通过 npm 安装:
npm install -g @q-code-cli/q-code
q-code全局安装后可直接更新到 npm latest:
q-code update
q-code update --dry-run # 仅查看将执行的更新命令更新后再次启动时,若版本高于上次使用记录(~/.q-code/last-version.json),会在 TUI / 经典模式下展示自上次版本以来的变更摘要;完整历史见 CHANGELOG.md(合并到 main 后由 CI 自动维护,发版时 pnpm build 会生成最新的 changelog.json)。设为 Q_CODE_CHANGELOG=0 可关闭启动提示。
首次使用可运行交互式初始化向导,生成 config.toml:
q-code init # 默认写入 ~/.q-code/config.toml
q-code init --local # 写入当前项目的 .q-code/config.toml
q-code init --user # 显式写入用户目录(与默认行为相同)向导会引导填写 OpenAI 兼容 API 的 base_url、api_key,通过 /models 接口校验并选择主模型与摘要模型,可选配置 [env].file 复用项目 .env;并可选开启 GitLab Wiki 集成(写入 [gitlab_kb] 的 url、token、prefix)。
也可以不全局安装,直接临时运行:
npx @q-code-cli/q-code本地开发时从源码安装依赖:
pnpm installnpm 全局安装后推荐使用 ~/.q-code/config.toml,在任意目录运行 q-code 都能读取:
[openai]
api_key = "sk-..."
base_url = "https://api.openai.com/v1"
model = "gpt-5.4"
[summary]
api_key = "sk-..."
base_url = "https://api.openai.com/v1"
model = "gpt-5.4"
[langfuse]
enabled = false
base_url = "https://cloud.langfuse.com"
record_io = false也可以在项目内使用 .q-code/config.toml 覆盖全局配置。配置优先级为:环境变量 > 项目 .q-code/config.toml > 全局 ~/.q-code/config.toml > 项目 .env > 内置默认值。
如果你想在 config.toml 里复用一份 .env 文件,可以这样写:
[env]
file = ".env.shared"
[openai]
model = "gpt-5.4"[env].file 支持相对当前 config.toml 的路径,先加载该 .env,再由同一个 config.toml 里的显式 TOML 键继续覆盖。
本地开发仍可复制环境变量模板并填写:
cp .env.example .env| 变量 | 必填 | 说明 |
|---|---|---|
OPENAI_BASE_URL |
❌ | OpenAI 兼容 API 地址,默认 https://api.openai.com/v1 |
OPENAI_API_KEY |
✅ | API Key |
OPENAI_MODEL |
❌ | 主模型名称,默认 gpt-5.4 |
Q_CODE_MODEL_PROVIDER |
❌ | 模型 provider 适配:auto / openai / deepseek-compatible,默认 auto。推荐只使用规范值 deepseek-compatible;中转服务使用别名模型时可显式设置 |
Q_CODE_THINKING_TYPE |
❌ | 通用 thinking 开关:enabled / disabled / adaptive。OpenAI 官方 provider 会把 disabled 映射为 reasoningEffort=none;DeepSeek V4 会映射为 thinking.type |
Q_CODE_REASONING_EFFORT |
❌ | 通用 reasoning 强度:none / minimal / low / medium / high / xhigh。DeepSeek V4 中 none 会关闭 thinking,xhigh 会映射为 max,其余可用档兼容到 high |
SUMMARY_BASE_URL |
❌ | 摘要模型 API 地址,默认复用 OPENAI_BASE_URL |
SUMMARY_API_KEY |
❌ | 摘要模型 API Key,默认复用 OPENAI_API_KEY |
SUMMARY_MODEL |
❌ | 摘要模型名称,默认复用 OPENAI_MODEL |
CONTEXT_LIMIT_TOKENS |
❌ | 上下文窗口上限,默认 256000 |
COMPACT_TRIGGER_RATIO |
❌ | 压缩触发比例,默认 0.85 |
WARNING_TRIGGER_RATIO |
❌ | 上下文预警比例,默认 0.80 |
BLOCKING_TRIGGER_RATIO |
❌ | 强制停止比例,默认 0.98,会预留普通输出预算 |
DEFAULT_MAX_OUTPUT_TOKENS |
❌ | 普通回答输出上限,默认 8000 |
ESCALATED_MAX_OUTPUT_TOKENS |
❌ | 输出触顶后的升级重试上限,默认 64000 |
COMPACT_MAX_OUTPUT_TOKENS |
❌ | 压缩摘要输出上限,默认 20000 |
Q_CODE_MODEL_WAIT_HEARTBEAT_MS |
❌ | 首 token 等待心跳阈值,默认 10000ms;设为 0 可关闭该档提示 |
Q_CODE_MODEL_SLOW_REQUEST_WARN_MS |
❌ | 首 token 慢请求提示阈值,默认 30000ms;设为 0 可关闭该档提示 |
Q_CODE_MODEL_STALLED_REQUEST_WARN_MS |
❌ | 首 token 长时间无响应提示阈值,默认 60000ms;设为 0 可关闭该档提示 |
Q_CODE_MODEL_REQUEST_TIMEOUT_MS |
❌ | 单步模型请求总超时,默认不启用;建议 OpenAI-compatible 中转按需设置 |
Q_CODE_PLAN_INTENT |
❌ | Plan Mode 语义入口:auto / suggest / off,默认 auto;pending plan 自然语言审批始终启用 |
Q_CODE_PLAN_INTENT_MODEL_TIMEOUT_MS |
❌ | pending plan 本地规则无法判断时的模型兜底超时,默认 3000ms;设为 0 关闭模型兜底 |
Q_CODE_SESSION_DIR |
❌ | 会话存储目录,默认 .sessions |
Q_CODE_HOME |
❌ | q-code 全局配置目录,默认 ~/.q-code |
Q_CODE_DEBUG |
❌ | 设为 1/true/yes/on 显示启动诊断信息(等价于 --debug) |
Q_CODE_CHANGELOG |
❌ | 启动时展示版本更新说明,默认开启;设为 0/false/off/no 可关闭 |
Q_CODE_STARTUP_TRACE |
❌ | 设为 1/true/yes/on 输出轻量启动阶段耗时;--debug 会自动启用 |
Q_CODE_THEME |
❌ | TUI Markdown / 代码块高亮主题,dark / light / auto,默认 auto |
Q_CODE_CACHE_STABLE_PREFIX_TARGET |
❌ | pnpm prompt:cache:verify 的稳定前缀目标,默认 0.9 |
Q_CODE_CACHE_KEEPALIVE_INTERVAL_MS |
❌ | 实验性 prompt cache keepalive 间隔毫秒,默认 0 关闭;小于 60000ms 会按 60000ms 执行 |
Q_CODE_AGENT_MD_FULL_CHAR_LIMIT |
❌ | 单个 AGENT/AGENTS 文件超过该字符数时进入稳定摘要,默认 16000 |
Q_CODE_AGENT_MD_SECTION_CHAR_LIMIT |
❌ | AGENT/AGENTS 摘要中单个关键章节保留字符数;非关键章节保留较短摘录,默认 1800 |
Q_CODE_AUDIT_ENABLED |
❌ | 审计日志开关,默认开启;设为 false/0/off/no 可关闭 |
Q_CODE_AUDIT_DIR |
❌ | 审计日志目录,默认 <Q_CODE_HOME>/logs |
Q_CODE_AUDIT_RETENTION_DAYS |
❌ | 审计日志保留天数,默认 30 |
Q_CODE_AUDIT_MAX_FILE_BYTES |
❌ | 单个审计文件最大字节数,默认 50MB,超出后追加序号轮转 |
Q_CODE_AUDIT_MAX_QUEUE_SIZE |
❌ | 审计写入内存队列上限,默认 1000 |
Q_CODE_AUDIT_PII |
❌ | 默认不写 prompt/tool 原文;设为 full 才写入原文 |
Q_CODE_CRASH_GUARD |
❌ | 崩溃保护开关,默认开启;设为 false 可关闭全局兜底 handler |
Q_CODE_HISTORY_DISABLED |
❌ | TUI 输入历史开关,默认 false;设为 true 后不加载/写入历史 |
Q_CODE_HISTORY_SCOPE |
❌ | 输入历史作用域:project / global / both,默认 both |
Q_CODE_HISTORY_REDACT |
❌ | 设为 true 后历史文件只保存 SHA-256 和前 40 字符摘要 |
Q_CODE_HISTORY_SEARCH |
❌ | Ctrl+R 搜索模式:substring / fuzzy,默认 substring |
Q_CODE_HISTORY_MAX_LINES |
❌ | 单个历史文件最大行数,默认 20000 |
Q_CODE_HISTORY_MAX_BYTES |
❌ | 单个历史文件最大字节数,默认 5MB |
Q_CODE_HISTORY_RUNTIME_LIMIT |
❌ | 启动时载入内存的最近历史数量,默认 2000 |
Q_CODE_HISTORY_MAX_LINE_BYTES |
❌ | 单条 JSONL 历史记录最大字节数,默认 32KB |
Q_CODE_TUI_CURSOR |
❌ | TUI 输入光标模式:ansi / inline / off;默认 inline(假光标) |
Q_CODE_TUI_CURSOR_BLINK_MS |
❌ | 假光标闪烁间隔毫秒,默认 500;仅在 Q_CODE_TUI_CURSOR=inline 时生效;设为 <=0 可禁用闪烁 |
Q_CODE_LANGFUSE_ENABLED |
❌ | Langfuse/OpenTelemetry 导出开关,默认 false |
LANGFUSE_PUBLIC_KEY |
❌ | Langfuse project public key,仅开启 Langfuse 时需要 |
LANGFUSE_SECRET_KEY |
❌ | Langfuse project secret key,仅开启 Langfuse 时需要 |
LANGFUSE_BASE_URL |
❌ | Langfuse 实例地址,默认 https://cloud.langfuse.com |
Q_CODE_LANGFUSE_RECORD_IO |
❌ | 是否上传 prompt/tool/输出原文,默认 false,仅传摘要 |
Q_CODE_LANGFUSE_SAMPLE_RATE |
❌ | Langfuse turn 采样率,0-1,默认 1 |
Q_CODE_LANGFUSE_ENVIRONMENT |
❌ | Langfuse environment 标签,可用于区分 dev/prod/self-hosted |
Q_CODE_LANGFUSE_RELEASE |
❌ | Langfuse release 标签,可用于关联版本或提交 |
Q_CODE_LANGFUSE_FLUSH_AT |
❌ | Langfuse span 批量 flush 条数,默认 20 |
Q_CODE_LANGFUSE_FLUSH_INTERVAL_SECONDS |
❌ | Langfuse 定时 flush 间隔秒数,默认 5 |
Q_CODE_LANGFUSE_TIMEOUT_SECONDS |
❌ | Langfuse 导出请求超时秒数,默认 5 |
Q_CODE_EVAL_JUDGE_BASE_URL |
❌ | LLM judge 专用 OpenAI 兼容 base URL;未设时回退 SUMMARY_BASE_URL |
Q_CODE_EVAL_JUDGE_API_KEY |
❌ | LLM judge 专用 API key;未设时回退 SUMMARY_API_KEY |
Q_CODE_EVAL_JUDGE_MODEL |
❌ | LLM judge 专用模型;未设时回退 SUMMARY_MODEL |
Q_CODE_MENTION_ALLOW_ABS |
❌ | 设为 true 后允许 @file 引用绝对路径;默认只允许当前目录内路径 |
Q_CODE_FILE_INDEX_IGNORE |
❌ | 非 git fallback walk 额外跳过的目录名,逗号分隔 |
Q_CODE_SHELL_TIMEOUT_MS |
❌ | f 同步命令默认超时,默认 60000ms |
Q_CODE_SHELL_TIMEOUT_MAX_MS |
❌ | f.timeoutMs 上限,默认 1800000ms(30 分钟) |
Q_CODE_SHELL_MAX_BUFFER |
❌ | f 同步输出内存阈值,默认 4194304(4MB),超出后落盘 spill |
Q_CODE_SHELL_ALLOW_ABS_CWD |
❌ | 设为 true 后允许 f.cwd 跳出当前工作目录 |
Q_CODE_SHELL_KILL_BG_ON_EXIT |
❌ | 设为 true 后 q-code 退出时清理仍在运行的 f 后台 job |
Q_CODE_SKILL_CHAR_BUDGET |
❌ | Skills discovery 注入字符预算,默认 8000 |
Q_CODE_TEAMS |
❌ | 设为 1/true/yes/on 开启 Agent Teams(等价于 --agent-teams) |
Q_CODE_INFRA_ENABLED |
❌ | 是否启用企业 AI 基建集成;默认 false,需显式设为 true |
Q_CODE_INFRA_BASE_URL |
❌ | 企业 AI 基建服务地址;仅在 Q_CODE_INFRA_ENABLED=true 时使用 |
Q_CODE_INFRA_TOKEN |
❌ | 企业 AI 基建访问令牌 |
Q_CODE_INFRA_CLIENT_ID |
❌ | Client 实例 ID;不填时自动生成并保存在 ~/.q-code |
Q_CODE_INFRA_SYNC |
❌ | 是否启用启动同步,默认 true;设为 false/0/off 关闭 |
Q_CODE_INFRA_TIMEOUT_MS |
❌ | 企业配置中心请求超时,默认 5000 |
Q_CODE_INFRA_USER_ID |
❌ | 企业用户 ID,用于配置匹配和审计 |
Q_CODE_INFRA_USER_GROUPS |
❌ | 企业用户组,逗号分隔 |
Q_CODE_GITLAB_KB_ENABLED |
❌ | 可选开关;设为 false/0/off 可强制关闭 GitLab Wiki 知识库 |
Q_CODE_GITLAB_URL |
❌ | GitLab 实例或项目地址;配置后启用 GitLab Wiki 知识库 |
Q_CODE_GITLAB_TOKEN |
❌ | GitLab Personal/Project Access Token,不会在输出中回显 |
Q_CODE_GITLAB_PROJECT_ID |
❌ | 可选 GitLab project id/path;不填时从 URL 或 git origin 推断 |
Q_CODE_GITLAB_KB_PREFIX |
❌ | Wiki 知识页前缀,默认 q-code-kb |
Q_CODE_GITLAB_KB_TIMEOUT_MS |
❌ | GitLab Wiki API 请求超时,默认 10000 |
MCP_CONNECT_TIMEOUT_MS |
❌ | MCP server 连接超时,默认 30000 |
GITHUB_PERSONAL_ACCESS_TOKEN |
❌ | 旧版 GitHub MCP 兼容入口;新配置建议使用 mcpServers |
TAVILY_API_KEY |
❌ | Tavily 搜索 API Key |
SERPER_API_KEY |
❌ | Serper 搜索 API Key |
q-code # npm 安装后的新会话
q-code --continue # 恢复上次会话
pnpm start # 新建会话
pnpm run continue # 恢复上次会话| 参数 | 说明 |
|---|---|
-h, --help |
输出帮助信息后退出 |
-v, --version |
输出版本号后退出 |
update |
将全局安装的 q-code 更新到 npm latest |
update --dry-run |
只显示更新命令,不实际执行 |
eval list [path...] |
列出固定 Agent eval case,默认读取 evals/smoke |
eval run [path...] |
运行 deterministic Agent eval,输出本地报告和 trace |
eval compare <a> <b> |
对比两个 eval run 的通过率、分数、进度、token 和成本变化 |
eval promote <run> --as <name> |
保存命名 baseline,供后续 compare 使用 |
eval trend |
汇总 .q-code/evals/runs 历史 run,生成趋势看板 |
--continue |
恢复上次会话 |
--session=<id> |
指定会话 ID |
--dump-system-prompt |
输出完整 System Prompt 后退出 |
--plan |
启动时直接进入 Plan Mode |
--agent-teams |
启用 Agent Teams 多智能体协作(也可设 Q_CODE_TEAMS=1) |
--classic |
使用传统 readline 交互,不启动 Ink TUI |
--no-color |
关闭 ANSI 语法高亮和颜色输出 |
--debug |
显示启动诊断信息,包括 Prompt Pipe 和工具加载概览 |
发布产物使用薄入口启动:help / version 只加载颜色环境、argv 解析和帮助/版本格式化后立即退出;update、audit、init、eval 与主交互循环按需动态加载各自模块,避免互相支付依赖成本。主交互路径也只在确认进入 TUI 时动态加载 Ink/React;非 TTY、--classic 或 Q_CODE_TUI=0 会回退到传统 readline,且不会加载 TUI 运行时。TUI 会先渲染会话和输入界面,再继续完成 Custom Tools、Hooks、Skills、Agents、MCP、runtime context 与项目指令预热;如果用户在预热完成前提交会触发 Agent 或依赖预热状态的命令,ready gate 会显示“正在完成启动预热...”并在能力完整后自动继续。需要观察阶段耗时时,可设置 Q_CODE_STARTUP_TRACE=true 或使用 --debug,输出形如 [Startup] bootstrap 12ms 的阶段计时,不包含 API key、token 或工具输出。
默认在交互式 TTY 中启动 Ink TUI。TUI 将 Agent 输出、工具调用、上下文占用、任务进度、SubAgent 状态和 token 用量统一渲染为事件流,支持 Ctrl+J 多行输入、Ctrl+R 历史搜索、Esc 清空/恢复输入、忙时 Ctrl+C 中断当前任务和 Markdown 代码块/列表/表格展示。多工具任务中,Agent 会在关键工具调用前后输出简短的公开进度说明;TUI 会按时间线把这些说明和工具调用交错展示,避免执行过程中只剩工具流水账。Markdown 行内内容会保留语义高亮:**重点**、inline code、URL、issue ref、文件路径和 src/foo.ts:123 行号会使用不同视觉通道,便于在长回复中快速定位关键信息。代码块使用 24-bit ANSI 主题 palette,TypeScript / TSX、diff 等内容在明暗终端中都保持较高对比;可通过 Q_CODE_THEME=dark|light|auto 控制配色,终端无法暴露背景色或 auto 判断不准时建议手动指定 light / dark,也可使用 --no-color / NO_COLOR=1 关闭全部颜色。输入区使用真实终端光标锚定输入法候选窗,避免 macOS IME 跑到屏幕角落。
在 TUI 输入框中输入 @ 后跟文件名片段,会出现基于仓库文件索引的 fuzzy 候选;使用方向键切换,Tab 插入当前候选。例如输入 @rou 可以补全到匹配的源码或文档路径。
提交消息时,@file 会把文件内容注入本轮用户上下文,并写入 user.mention 审计事件。支持以下形式:
请解释 @src/runtime/cli-info.ts
只看一行 @src/runtime/cli-info.ts:42
只看范围 @src/runtime/cli-info.ts:10-30
定位正则 @src/runtime/cli-info.ts:#getEarlyCliCommand
路径含空格 @"My Project/notes.md"
默认只允许引用当前工作目录内的文件,并会校验 symlink 指向的真实路径;绝对路径如 @/etc/passwd 会被阻止,确需引用绝对路径时设置 Q_CODE_MENTION_ALLOW_ABS=true。单个引用最多注入 50KB,单轮全部引用合计最多 200KB,超出时会截断或明确提示丢弃。文件工具的读类入口(read_file / list_directory / glob / grep)除当前目录外,还可只读访问用户级 q-code 信任目录:~/.q-code、~/.agents/skills、~/.agents/agents;写入和编辑仍限制在当前工作目录内。文件候选优先使用 git 索引,非 git 目录会回退递归扫描;索引会缓存到 <cwd>/.q-code/file-mention-index.json,下次启动先用缓存并在后台刷新。TUI 会监听文件变更并 debounce 刷新候选;如果 watcher 不可用,会显示简短提示并降级为定时刷新。刷新失败时继续使用旧索引;超过 20000 个文件时候选会裁剪并在 TUI 中提示。fallback walk 默认跳过 .q-code、.sessions 等本地目录,可用 Q_CODE_FILE_INDEX_IGNORE=build,out 追加忽略目录。
仓库已配置为可发布的 npm CLI 包:
bin.q-code指向dist/index.jsprepack会自动执行npm run buildprepublishOnly会自动执行 typecheck 和全量测试- 发布包只包含
dist/、README.md、LICENSE和.env.example
发布前检查:
pnpm install
pnpm typecheck
pnpm test
npm pack --dry-run确认 npm 登录态和 q-code-cli 组织权限后发布:
npm publish --access publicsrc/
├── index.ts # 开发态兼容入口,委托给 cli/bootstrap.ts
├── cli/
│ ├── bootstrap.ts # 薄 CLI 入口:early commands、动态 import 和启动 trace
│ ├── main.ts # 主交互循环、模式切换、上下文压缩调度
│ └── startup-ready.ts # 启动预热 ready gate
├── agent/
│ ├── loop.ts # Agent Loop 核心(ReAct 模式)
│ ├── loop-detection.ts # 死循环检测
│ └── retry.ts # 步骤级重试 + 指数退避
├── context/
│ ├── prompt-builder.ts # System Prompt 管道组装
│ ├── compressor.ts # Microcompact + Summarization
│ ├── offload.ts # Context Offloading:大工具结果落盘
│ ├── token-budget.ts # 上下文 token 估算与状态追踪
│ ├── auto-compact.ts # 压缩熔断器
│ ├── agent-md.ts # AGENT.md 项目指令加载
│ ├── plan-attachments.ts# Plan Mode 内部提醒
│ ├── plan-intent.ts # Plan Mode 自然语言审批与智能进入规则
│ ├── plans.ts # 计划文件读写
│ ├── project-paths.ts # 项目存储路径计算
│ ├── runtime-context.ts# 运行环境信息采集
│ ├── tasks.ts # Task V2 持久化任务图
│ ├── todos.ts # TodoWrite V1 会话级状态
│ └── memory/
│ ├── memdir.ts # 项目记忆文件读写与索引管理
│ └── memory-types.ts# 记忆类型定义与引导指令
├── session/
│ └── store.ts # JSONL 会话持久化
├── mentions/ # @file 文件引用解析、索引缓存/刷新、fuzzy 补全和上下文注入
├── skills/ # SKILL.md 加载、渐进式披露、条件激活
├── agents/
│ ├── bootstrap.ts # SubAgent 启动加载
│ ├── registry.ts # SubAgent 注册表
│ ├── load-agents-dir.ts# 自定义 Agent 文件加载
│ ├── resolve-agent-tools.ts# 子 Agent 工具过滤
│ ├── run-agent.ts # 同步子 Agent 执行
│ ├── run-async-agent.ts# 后台子 Agent 生命周期
│ ├── async-agent-store.ts# SubAgent 运行状态表
│ ├── notification-store.ts# 后台任务完成通知队列
│ ├── task-output.ts # SubAgent JSONL 输出
│ ├── worktree.ts # Git worktree 隔离
│ └── built-in/ # 内置 SubAgents
├── tools/
│ ├── index.ts # 工具注册入口
│ ├── registry.ts # 工具注册表(并发控制、延迟加载)
│ ├── file-tools.ts # 文件读写编辑
│ ├── shell-tools.ts # Shell 命令执行
│ ├── search-tools.ts # 网络搜索 / 网页抓取
│ ├── memory-tools.ts # 项目记忆写入工具
│ ├── plan-tools.ts # Plan Mode 工具
│ ├── task-tools.ts # Task V2 工具
│ ├── todo-tools.ts # TodoWrite V1 工具
│ ├── utility-tools.ts # glob / grep / URL 抓取 / 预览
├── terminal/
│ ├── events.ts # 终端事件总线;TUI、未来 A2A 共享事件协议
│ ├── state.ts # TUI transcript/status reducer
│ ├── App.tsx # Ink 交互界面
│ ├── input.ts # 输入编辑、历史和提交状态机
│ ├── history-store.ts # TUI 输入历史 JSONL 持久化、过滤与轮转
│ └── markdown.ts # 轻量 Markdown block 渲染
├── mcp/
│ ├── config.ts # MCP settings.json 配置加载
│ ├── client.ts # MCP SDK client + stdio/http/sse transport
│ ├── fetch-tools.ts # MCP tool → q-code ToolDefinition 适配
│ ├── bootstrap.ts # 非阻塞启动、重连和注册表刷新
│ ├── registry.ts # MCP server 连接状态注册表
│ ├── names.ts # MCP 工具名 normalization
│ └── types.ts # MCP 配置和连接状态类型
└── utils/
├── index.ts
└── logger.ts # 格式化输出
┌─────────────────────────────────────────────────────────────┐
│ 启动阶段 │
│ │
│ 1. 薄入口处理 help/version;其他子命令按需动态 import │
│ 2. 主交互路径加载环境变量,初始化会话/历史/模型基础状态 │
│ 3. 仅 TUI 模式动态加载 Ink/React,并先渲染输入界面 │
│ 4. 显式 startupWarmupPromise 并行预热 Hooks/Custom Tools/Infra│
│ 5. 继续并行加载 runtime context、项目指令、MCP、Skills、Agents │
│ 6. ready gate 在预热完成后注册完整工具并构建 System Prompt │
│ 7. 用户输入若早于预热完成,会等待 gate 后继续执行 │
└───────────────────────────┬─────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ 交互循环 (readline) │
│ │
│ 用户输入 ──→ 斜杠命令? ──→ 是 ──→ 处理内置命令 │
│ │ │
│ 否 → Skill 斜杠展开? → 是 → 展开为消息 │
│ │ │
│ 否 → 构造 user message │
│ │
│ ──→ 注入后台 Agent 完成通知 (如有) │
│ ──→ 注入 Plan Mode 提醒 (如需) │
│ ──→ 保存消息到 SessionStore │
│ ──→ 动态构建 System Prompt (buildSystemPrompt) │
│ ──→ 进入 Agent Loop │
└───────────────────────────┬─────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ Agent Loop (无默认步数硬限制) │
│ │
│ ┌──→ Step N: │
│ │ 1. Preflight: 检查上下文占用,超阈值则压缩 │
│ │ 2. 流式调用 LLM (streamText) │
│ │ 3. 收集工具调用 / 文本输出 │
│ │ 4. 输出触顶? → 升级 maxOutputTokens 重试 │
│ │ 5. 执行工具 (并发控制 + 结果截断) │
│ │ 6. 死循环检测 (三种检测器) │
│ │ 7. stopAfterToolNames 检查 (如 exit_plan_mode) │
│ │ 8. 无工具调用 → 退出循环 │
│ └─── 有工具调用 → 继续 │
│ │
└───────────────────────────┬─────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ 后处理阶段 │
│ │
│ 1. 保存新消息到 SessionStore │
│ 2. Post-turn 压缩检查 (为下一轮腾出空间) │
│ 3. Plan Mode 审批提示 (如有待确认计划) │
│ 4. 回到交互循环,等待下一轮输入 │
└─────────────────────────────────────────────────────────────┘
采用 ReAct(推理-行动交替)模式,主会话不再按默认步数或执行 token 预算硬停:
- 构建 System Prompt — 根据用户输入动态构建
buildSystemPrompt(userQuery),使记忆上下文响应当前意图 - Preflight — 检查上下文占用,超阈值则压缩
- LLM 推理 — 流式调用模型
- 工具执行 — 根据模型输出执行对应工具
- 循环检测 — 识别重复调用并干预
- 早停检查 — 如
exit_plan_mode等 stopAfterToolNames 命中则停止 - 无工具调用时退出循环
步骤级重试:失败自动重试最多 3 次,带指数退避。
输出触顶升级:普通输出 8000 token;因 length 触顶且无工具调用时,升级到 64000 token 重试一次。
q-code 采用 JIT Context 策略:上下文不在启动时一次性塞满,而是在任务推进到需要证据时再逐步进入模型。目标是减少 Context Rot,降低大仓库、多工具和长会话下的无效 token。
System Prompt 会注入固定的 JIT 纪律:
- 不要一开始批量读取可能无关的大文件、网页或长命令输出
- 代码/文件探索优先走
list_directory/glob → grep → read_file,先定位路径和行号,再读取精确片段 - 只把能推进当前判断的最小证据放进主上下文
- 宽搜索、噪音探索或可并行调查优先交给
Agent/Explore,主上下文只接收摘要 - Skills、SubAgents、MCP 工具都按渐进式披露工作:先看名称/摘要/Schema,必要时再加载正文或执行高成本工具
System Prompt 管道只保留高稳定前缀:核心规则、项目指令、稳定工具纪律、稳定 Skill 调用纪律、SubAgents 摘要和稳定延迟工具纪律。当前可见 Skill 列表、延迟工具列表、Plan/Task/Todo、Agent Teams 活跃状态、运行环境、项目记忆、会话信息和长报告提示等本轮动态内容,会通过 Agent Loop 的 transientMessages 追加为本轮尾部 user context,不进入 system prompt,也不写入会话历史。这样即使日期、Git 状态、条件 Skill 激活、延迟工具发现、任务图或 query-specific memory 改变,也不会切断前面的大块 provider prompt cache。
AGENT.md / AGENTS.md 超过 Q_CODE_AGENT_MD_FULL_CHAR_LIMIT 时会以稳定摘要进入 system prompt:所有章节都会保留标题与确定性摘录,项目概览、环境、常用命令、CLI、目录边界、实现约定、测试策略、Git 注意事项、Security、Testing、Repository Guidelines 等关键章节会获得更长预算;完整内容仍可按需 read_file 读取。这样项目级协作说明仍在稳定前缀中,但不会因为超长文档拖低 cache 复用率。
运行环境默认只注入日期粒度时间和 Git 摘要:clean 或 dirty (N changed files);如需完整文件列表,模型应通过工具按需查询。/cache status 会显示整体 system/tools hash、稳定前缀比例、每个 prompt pipe 的分段 hash/changed/stability/category 状态、逐工具 schema hash,以及实验性 keepalive 是否开启,用于定位是哪一段或哪一个工具在抖动。clean 工作区和普通多轮会话下,稳定前缀比例目标应保持在 90% 以上;可运行 pnpm prompt:cache:verify 在本地构建两次稳定 prompt 并检查 Q_CODE_CACHE_STABLE_PREFIX_TARGET。
Q_CODE_CACHE_KEEPALIVE_INTERVAL_MS 默认关闭。开启后,q-code 只会在空闲、已有本轮稳定 system prompt、且 /cache 模式不是 off 时发送极短后台请求,尝试维持供应商侧 cache 热度;小于 60000ms 的配置会自动按 60000ms 执行,并且单次后台请求会在超时、切换模型/会话或退出时取消。这会产生额外模型调用和少量 usage 记录,真实命中率仍受供应商 TTL、模型、tool schema 与 tokenization 影响。
每个工具可以声明 JIT 元数据:
| 字段 | 说明 |
|---|---|
contextCost |
low / medium / high,表示结果进入上下文的成本 |
resultShape |
结果形态,如 paths、lines、file、web、state |
jitHint |
给模型的简短使用建议 |
ToolRegistry.getJitToolSummary() 会按当前 active 工具生成“工具成本阶梯”,并注入 System Prompt。典型分层:
| 成本 | 典型工具 | 使用方式 |
|---|---|---|
| 低成本 | list_directory、glob、task_list |
先看轮廓、路径、轻量状态 |
| 中成本 | grep、web_search、Skill、Agent |
定位匹配行、拿摘要、隔离宽探索 |
| 高成本 | read_file、web_fetch、f |
只在目标明确后读取全文或长输出 |
MCP 工具默认 shouldDefer: true,只有通过 tool_search 激活后才进入 active 工具列表;其元数据也会随 Schema 返回,保持外部工具的渐进式披露。
当上下文占用 ≥ 85%(COMPACT_TRIGGER_RATIO)或手动 /compact 触发压缩时,q-code 会先执行 Context Offloading,再进入 microcompact 和摘要:
- Context Offloading — 将大工具结果的原文写入磁盘,只在消息里保留 marker、绝对路径、字符数、恢复说明和头尾预览
- Microcompact — 清理旧工具结果,替换为占位符,保留最近 3 个;已 offload 的 marker 会被保留,避免丢失恢复路径
- Summarization — 用独立的摘要模型将旧对话压缩为结构化摘要(用户意图 / 已完成操作 / 关键发现 / 当前状态 / 需保留细节),保留最近 8 条消息
Offload 文件路径:
.sessions/projects/<projectKey>/offloads/<sessionId>/tool-result-0001-<hash>.txt
marker 示例:
[tool result offloaded]
tool: read_file
original_chars: 24000
file: /abs/path/.sessions/projects/<projectKey>/offloads/<sessionId>/tool-result-0001-<hash>.txt
restore: 如需完整原始工具结果,使用 read_file 读取上面的 file 路径。
preview:
...
Offloading 是无损的:摘要模型只看到短 marker 和预览,后续 Agent 如果确实需要完整结果,可以用 read_file 读取 marker 中的文件路径。
触发时机:
| 时机 | 说明 |
|---|---|
| Preflight | Agent Loop 每一步调用 LLM 前 |
| Post-turn | 每轮对话结束后,为下一轮腾出空间 |
手动输入 /compact 可立即压缩当前会话;压缩熔断器会在连续 3 次自动压缩未能减少上下文时停止尝试,手动压缩不受熔断器拦截。
| 命令 | 说明 |
|---|---|
/context |
查看当前 system prompt、工具 schema、消息、压缩余量和输出预留矩阵 |
/usage |
查看输入/输出 token、cache read/write、实际成本、无 cache 基线和节省 |
/cost |
/usage 的兼容别名 |
/cache / /cache status |
查看当前 cache 模式、cache 命中统计和 system/tools prefix 稳定性 |
/cache auto |
默认模式:追踪供应商 cache,并只在安全时启用 q-code 显式 cache hints |
/cache on |
允许 q-code 对支持的供应商启用显式 cache hints |
/cache off |
关闭 q-code 显式 cache hints;供应商隐式 cache 仍可能命中并上报 |
| `/status [on | off |
/usage 的成本估算基于内置模型价格表;未知模型仍会统计 token/cache,但成本项会标注不可用。/cache off 不能关闭 OpenAI、DeepSeek 等供应商侧的隐式 prompt cache,它只控制 q-code 自身未来可启用的显式 cache hint 策略。
Q_CODE_THINKING_TYPE 与 Q_CODE_REASONING_EFFORT 是通用 reasoning 配置,会应用到主 Agent、SubAgent、摘要压缩、real-agent eval 与 LLM judge。OpenAI 官方 provider 通过 providerOptions.openai.reasoningEffort 接收强度;Q_CODE_THINKING_TYPE=disabled 仅会在明确的 OpenAI reasoning 模型上映射为 reasoningEffort=none,避免普通兼容模型因未知参数失败。默认 Q_CODE_MODEL_PROVIDER=auto 会在 OPENAI_BASE_URL 或 OPENAI_MODEL 包含 deepseek 时改用官方 @ai-sdk/openai-compatible provider;如果中转服务隐藏了 DeepSeek URL/模型名,可显式设置 Q_CODE_MODEL_PROVIDER=deepseek-compatible(deepseek / openai-compatible-deepseek 仅作为兼容别名保留)。DeepSeek V4 thinking/tool-call 兼容层会把响应里的 reasoning_content 映射为 AI SDK reasoning part 保留在 assistant 消息历史中,并在带工具调用的后续请求里原样回填到 OpenAI-compatible API 的 reasoning_content 字段;deepseek-v4-pro 默认显式发送 thinking.type=enabled 与 reasoning_effort=high,Q_CODE_REASONING_EFFORT=none 会关闭 thinking,xhigh 会映射为 DeepSeek 的 max。V4 Pro thinking + tools 时,默认 tool_choice=auto 会被兼容层移除;显式指定 required 或具体函数会报清晰错误,避免静默吞掉调用意图。这类 reasoning 不会作为普通 assistant 文本流输出到 TUI。
q-code 默认开启本地审计日志,按 UTC 日期写入 <Q_CODE_HOME>/logs/audit-YYYY-MM-DD.ndjson。每一行是一条 JSON 事件,便于 tail -f、归档到 SIEM/ELK,或在故障后按 sessionId 和时间窗回放关键行为。
公共字段:
| 字段 | 说明 |
|---|---|
ts |
UTC ISO8601 时间戳 |
seq |
当前进程内自增序号 |
pid |
进程号 |
sessionId |
会话 ID |
agent |
main / subagent / teammate 上下文 |
event |
事件名 |
payload |
事件负载 |
首期覆盖事件包括 session.start / session.resume / session.end、user.prompt、agent.step.start / agent.step.end、tool.call / tool.result、hook.decision、mode.change、plan.markReady / plan.approve / plan.revise、subagent.*、team.*、context.compact / context.offload 和 error。agent.step.end 会附带 ttftMs、elapsedMs、outputTokens、tokensPerSecond,用于区分首 token 慢、总生成慢或 token 吞吐低。
默认 PII 模式不会把用户输入、工具输入、工具输出原文写入日志,只记录 chars、inputChars、resultLength 和 sha256 摘要。只有显式设置 Q_CODE_AUDIT_PII=full 时,才会把原文写入 payload.text / payload.input / payload.output,建议仅在企业内网或短期调试时使用。
日志文件默认单文件 50MB,超出后写入 audit-YYYY-MM-DD.1.ndjson、audit-YYYY-MM-DD.2.ndjson。启动时会清理超过 Q_CODE_AUDIT_RETENTION_DAYS 的旧文件;写入采用异步串行队列,失败只输出 [audit] 警告,不阻塞 Agent 主流程。
CLI 校验与查询:
q-code audit verify --from 2026-05-25 --to 2026-05-25
q-code audit tail --session <sessionId> --event tool.result --followLangfuse 是可选的 OpenTelemetry 导出后端,默认关闭。开启后 q-code 会把每轮 turn、Agent step、AI SDK generation、工具调用和 token usage 作为 Langfuse trace/observation 上报;本地 NDJSON audit 和后续 .q-code/evals 仍是源数据,不依赖 Langfuse 才能运行。
推荐在全局或项目 .q-code/config.toml 中配置:
[langfuse]
enabled = true
public_key = "pk-lf-..."
secret_key = "sk-lf-..."
base_url = "https://langfuse.example.com"
record_io = false
sample_rate = 1默认 record_io=false,不会上传完整 prompt、文件内容、shell 输出或工具结果,只上报字符数、SHA-256 摘要、工具名、耗时、token 和错误状态。只有显式设置 Q_CODE_LANGFUSE_RECORD_IO=true / record_io = true 时,才会把输入输出原文交给 Langfuse,建议仅用于自托管实例或短期调试。
模型首个可见输出等待超过 10/30/60 秒时,TUI 状态栏或 classic stderr 会显示“正在等待模型响应...”心跳;这些提示不会进入会话 transcript。开启 Langfuse 后,Agent step observation 同步记录 ttftMs、elapsedMs、tokensPerSecond、outputTokens 和最近一次模型等待状态,方便对比 OpenAI-compatible 中转排队、上游限速与长上下文生成慢。
q-code eval 是本地优先的 Agent 回归框架,默认用 mock model / mock tool 跑 deterministic case,不需要真实模型 API key,也不会进入普通会话、MCP 或 TUI 初始化。每次 run 会写出:
完整维护指南见 docs/agent-evals-guide.md。
.q-code/evals/runs/<run-id>/
├── run.json
├── cases.jsonl
├── report.md
└── traces/<case-id>-<repeat>.jsonl
常用命令:
q-code eval list evals/smoke
q-code eval list evals/smoke --tag budget
q-code eval run evals/smoke --no-langfuse
q-code eval run evals/cli --no-langfuse
q-code eval run evals/smoke evals/cli --tag regression --concurrency 2 --report json,md,junit --max-cases 20 --max-duration-ms 60000 --max-cost-usd 0.05
q-code eval run evals/smoke --repeat 3 --langfuse
q-code eval run evals/smoke --langfuse --langfuse-datasets
q-code eval run evals/live --allow-real-model --judge --max-cost-usd 0.05
q-code eval promote .q-code/evals/runs/<run-id> --as main
q-code eval compare main .q-code/evals/runs/candidate
q-code eval trend --limit 30case 文件支持 mock-agent、cli-subprocess 与 real-agent 三种模式。mock-agent 用脚本化 mock model/mock tool 验证最终输出、工具轨迹和预算;cli-subprocess 会把 setup.fixture 复制到隔离 workspace,执行 cli.command + cli.args,再评分 stdout/stderr、退出码、文件副作用和 workspace diff;real-agent 会复用真实 agentLoop + ToolRegistry + OPENAI_* 模型配置,但必须传 --allow-real-model 才会执行,默认只暴露只读工具,写文件或 shell 工具必须在 case 的 real.tools 中显式列出。断言支持 final.contains/regex、trajectory.strict|unordered|subset、requiredTools/forbiddenTools、maxExtraTools、expectedSteps、budgets.maxSteps/maxToolCalls/maxTotalTokens/maxDurationMs/maxCostUsd、sideEffects.files[].contains/regex、sideEffects.gitDiff、safety.forbidSecrets、safety.forbiddenOutputPatterns、safety.forbiddenToolInputPatterns、safety.forbiddenToolOutputPatterns、safety.forbiddenPaths、checkpoints 和 opt-in judge.rubric/threshold/includeTrace。报告会输出 success、progressRate、progressTimeline、judgeScore、errorType、toolExecutionValidity、toolMetrics、usage、estimatedCostUsd、difficulty breakdown、失败复现命令、trace、stdout/stderr 与 workspace 路径。
list 与 run 支持 --grep、--tag、--exclude-tag、--difficulty、--mode 过滤 case;run 还支持 --max-cases、--max-duration-ms、--max-total-tokens、--max-cost-usd 作为运行级闸门,超过时会生成 __run_limits__.* 失败结果并让命令非零退出。成本按 src/usage/pricing.ts 的模型价格表估算,mock eval 使用 q-code-eval-mock 价格项;缺少价格表的真实模型 case 会保留 token 指标并标记 unknown cost。--judge 才会运行 LLM judge,默认用 Q_CODE_EVAL_JUDGE_*,未配置时回退 SUMMARY_*。--report 支持 json,md,junit,其中 run.json 与 cases.jsonl 始终写出;junit.xml 用于 CI 展示。q-code eval promote 会把一次 run 复制到 .q-code/evals/baselines/<name>/,之后可以用 q-code eval compare <name> <candidate> 直接对比命名 baseline;q-code eval trend 会读取 .q-code/evals/runs/*/run.json,写出 .q-code/evals/trends/trend.json 与 trend.md,用于查看 pass rate、score、progress、tokens、cost 的长期变化。
这套 eval 指标对应一个最小 Agent 质量平台闭环:任务成功率看 success/passRate,过程质量看 trajectory 与 progressTimeline,工具可靠性看 toolExecutionValidity/toolMetrics,效率看 steps/tokens/duration/cost,责任安全看 safety/policy scorer,语义质量看 opt-in LLM judge,回归治理看 baseline promote/compare、趋势看板、JUnit CI 和 .github/workflows/eval-nightly.yml 定期回归。开启 Q_CODE_LANGFUSE_ENABLED=true 时,eval run 会额外导出为 Langfuse q-code.eval.run evaluator trace,每个 case 作为 evaluator observation 记录 score、progressRate、errorType、工具指标、token 和估算成本;加 --langfuse-datasets 后还会通过 Langfuse Public API 写 dataset item、dataset run item 和 scores。Langfuse 导出失败不会让本地 eval 失败;.q-code/evals 仍是评测真源。
q-code 默认启用崩溃保护。遇到未捕获异常、未处理 Promise rejection 或退出信号时,会尽量恢复终端状态、清理 MCP/后台 Agent 资源、写入审计错误事件,并在 <Q_CODE_HOME>/crashes 下生成 crash-<sessionId>-<timestamp>.json。
崩溃报告包含 package version、Node/平台信息、sessionId、cwd、当前模型、模式、最后一次用户输入摘要、最后一次工具调用、后台 Agent/MCP 脱敏快照、错误堆栈和内存快照。若崩溃发生在 assistant 流式输出中,会向当前会话追加 [crashed mid-stream] 标记,方便 q-code --continue 恢复时识别上一轮未完成。
可通过 Q_CODE_CRASH_GUARD=false 关闭该兜底 handler。关闭后未捕获异常会回到 Node 默认行为,不再生成 crash 报告。
预算状态分三级:
| 状态 | 阈值 | 行为 |
|---|---|---|
warning |
≥ 80%(WARNING_TRIGGER_RATIO) |
提醒上下文吃紧 |
error |
≥ 85%(COMPACT_TRIGGER_RATIO) |
触发自动压缩 |
blocking |
≥ 98%(BLOCKING_TRIGGER_RATIO) |
停止下一次模型请求 |
blocking 阈值会同时参考 BLOCKING_TRIGGER_RATIO 和普通输出预算,避免输入已经贴近窗口上限时还发起请求。
模型输出分三档:普通回答默认 8000 token;如果模型因为 length 触顶且本步没有工具调用,会用 64000 token 重试一次;压缩摘要默认 20000 token,避免长会话摘要被截断。
三种检测器并行工作:
| 检测器 | 触发条件 | 警告 | 强制停止 |
|---|---|---|---|
generic_repeat |
同一工具 + 相同参数重复调用 | ≥5 次 | ≥8 次 |
ping_pong |
两个工具交替循环 | ≥5 次 | ≥8 次 |
global_circuit_breaker |
同一工具无进展重复 | — | ≥10 次 |
warning 级别注入系统提醒,critical 级别直接终止循环。
| 类别 | 工具 | 功能 |
|---|---|---|
| 文件操作 | read_file / write_file / edit_file / list_directory |
读写编辑文件、列出目录 |
| Shell | f / f_status / f_tail / f_kill / f_list |
Shell 命令执行、后台长任务和输出增量读取 |
| 搜索 | glob / grep / pick_search |
文件搜索 / 内容搜索 / 代码库语义搜索 |
| 网络 | fetch_url / web_fetch |
网页抓取 |
| 实用 | start_preview |
本地预览服务 |
| 记忆 | memory_write |
跨对话项目记忆写入 |
| 技能 | Skill |
按需加载并执行 SKILL.md 工作流 |
| 子代理 | Agent |
同步或后台启动独立上下文的 SubAgent,支持 worktree 隔离 |
| 计划 | enter_plan_mode / plan_write / exit_plan_mode |
Plan Mode 切换、计划写入与提交 |
| 任务 V2 | task_create / task_update / task_get / task_list |
Task V2 持久化任务图 |
| 待办 V1 | todo_write |
TodoWrite V1 会话级任务清单,全量替换,全部完成自动清空 |
| 动态发现 | tool_search |
延迟工具动态发现 |
f 默认执行同步命令,Windows 优先使用 PowerShell7(pwsh),缺失时回退到 Windows PowerShell 5.1(powershell.exe),其他平台使用 Bash。参数支持 cwd、timeoutMs、maxBufferBytes、stdin、env、label 和 background:
- 同步模式默认超时 60s,受
Q_CODE_SHELL_TIMEOUT_MS控制;用户传入的timeoutMs会被Q_CODE_SHELL_TIMEOUT_MAX_MS限制。 - 输出超过
maxBufferBytes(默认 4MB)不会杀进程,会把完整输出写入<Q_CODE_HOME>/shell-spills/<jobId>.log,工具结果返回 head/tail 摘要和文件路径。 - 执行过程中 stdout/stderr 会以节流进度写入 TUI 的 JIT 状态;
--classic下会直接打印进度行。 cwd默认只能位于当前工作目录内;确需跳出时设置Q_CODE_SHELL_ALLOW_ABS_CWD=true。- 交互提示(如
password:、(y/n)、Enter ...)会在短暂宽限后终止并返回interactive_not_supported;针对根目录的rm -rf /(含-fr、拆分-r/-f、--recursive/--force长选项、sudo rm -rf /等常见写法)、fork bomb、mkfs、危险dd会直接拦截。
后台模式使用 f({ command, background: true }),立即返回 jobId、pid、outputFile 和 startedAt。后续可用:
| 工具 | 说明 |
|---|---|
f_status |
查看 job 的 running/completed/failed/killed、退出码和耗时 |
f_tail |
按 fromOffset / maxBytes 增量读取输出文件 |
f_kill |
终止后台 job 的进程树 |
f_list |
列出当前进程内已知 shell job |
后台 job 元数据会追加到 <Q_CODE_HOME>/shell-jobs/<sessionId>.index。默认退出 q-code 不主动杀后台 job;可设置 Q_CODE_SHELL_KILL_BG_ON_EXIT=true,或在 settings.json 中配置:
{
"shell": {
"killBackgroundOnExit": true
}
}q-code 支持从两个目录扫描“目录式”自定义工具,并按固定优先级覆盖同名工具:
<cwd>/.q-code/tools/<tool-name>/~/.q-code/tools/<tool-name>/- 内置工具
每个工具目录至少包含一个 schema.json,格式为:
{
"name": "demo_tool",
"description": "示例自定义工具",
"parameters": {
"type": "object",
"properties": {
"value": { "type": "string" }
},
"required": ["value"],
"additionalProperties": false
},
"isReadOnly": true,
"isConcurrencySafe": true,
"execute": "node ./index.js"
}约定说明:
schema.json结构为Omit<ToolDefinition, 'isEnabled' | 'execute'> & { execute: string }- 工具目录名必须与
schema.json.name完全一致 - 子目录缺少
schema.json时会在启动时输出[tools] Skipping …警告并跳过 execute是可在 shell 中直接执行的命令,执行目录固定为当前工具目录- 工具目录中可以放置任意配套文件,例如
index.js、模板、脚本或静态资源 - 运行时会把工具输入通过
stdin传给命令,默认 payload 为:
{
"version": 1,
"input": { "value": "hello" },
"context": {
"cwd": "/abs/project",
"sessionId": "optional-session-id"
}
}- 命令
stdout如果是合法 JSON,会按结构化工具结果解析;否则按普通文本结果返回 - 命令非零退出、超时、输出过大或启动失败时,会转成结构化工具错误并进入现有审计/Hooks 管线
isConcurrencySafe工具可并发执行- 非 safe 工具独占执行,互斥等待
- 工具可声明
contextCost/resultShape/jitHint,System Prompt 会自动生成当前工具成本阶梯 - 工具结果超过各自
maxResultChars时自动截断(保留头 60% + 尾部) - 工具执行上下文带
cwd,子 Agent 使用 worktree 隔离时,文件、Shell、grep/glob、记忆写入等工具都会相对 worktree 执行
Plan Mode 是"只看不动"的规划模式,适合复杂、多文件、需要先确认方案的任务。q-code 不引入权限系统,而是在每次模型请求前动态过滤工具列表:Plan Mode 下只暴露只读工具、plan_write 和 exit_plan_mode,隐藏 write_file、edit_file、f、memory_write 等会修改项目或环境的工具。
计划文件存储在 .sessions/projects/<projectKey>/plans/<sessionId>.md。模型完成探索后会写入计划并调用 exit_plan_mode,当前 loop 会停住等待用户确认,避免"退出计划后立刻实现一遍、审批后又实现一遍"的问题。
计划待确认时,可以直接回复自然语言:可以、开始吧、ok、go 等会批准并执行;补充测试策略、调整风险说明 等会作为反馈继续规划;退出计划模式 或 取消 会回到 normal 且不执行。否定语义优先,例如 不要执行、先别开始 不会误判为批准。本地规则无法判断时,会用当前会话模型做一次短超时 JSON intent judge 兜底;模型失败、超时或低置信度时仍回退到提示,不会猜测执行。
普通输入也会做保守的本地语义判断:明确说 先给方案、只分析不要修改、评估风险 时会自动进入 Plan Mode;复杂执行型请求会建议先规划,不会静默强制切换。TUI 会保留原请求并显示确认条:按 Enter 进入 Plan Mode 后继续原请求,按 Esc 按普通模式执行,按 Ctrl+C 取消且不执行。classic readline 只打印建议并继续执行当前请求。可用 Q_CODE_PLAN_INTENT=auto|suggest|off 控制智能入口;Q_CODE_PLAN_INTENT_MODEL_TIMEOUT_MS=0 可关闭 pending plan 模型兜底。TUI 中按 Shift+Tab 可切换 normal / plan,无法捕获该快捷键的终端可继续使用 /mode toggle。
| 命令 | 说明 |
|---|---|
/mode |
查看当前模式和计划文件路径 |
/mode plan |
手动进入 Plan Mode |
/mode normal |
手动回到 normal 模式 |
/mode toggle |
切换 Plan / normal 模式 |
/plan |
查看当前计划文件内容 |
/approve-plan |
批准计划并切回 normal 模式执行 |
/revise-plan <反馈> |
不批准当前计划,带反馈继续规划 |
用文件级持久化任务图跟踪复杂工作。适合多步骤、跨回合、带依赖关系的任务;Plan Mode 下也允许使用,因为它只修改任务状态,不改项目文件或外部环境。
存储结构:
.sessions/projects/<projectKey>/tasks/<sessionId>/
├── 1.json
├── 2.json
└── .highwatermark
每个任务一个 JSON 文件,.highwatermark 记录最大已分配 id。即使删除任务或 /tasks reset 清空当前任务图,后续新任务也不会复用旧 id。
任务字段:
| 字段 | 说明 |
|---|---|
id |
稳定递增的字符串 id |
subject |
祈使句单行标题,例如"运行测试" |
description |
任务细节和验收标准 |
activeForm |
进行中文案,可选 |
status |
pending / in_progress / completed |
blocks |
当前任务阻塞的下游任务 id |
blockedBy |
阻塞当前任务的上游任务 id |
metadata |
可选元信息,task_update 里传 null 可删除 key |
工具约定:
task_create创建任务,返回Task #<id> created: <subject>task_list列出当前任务图;pending且所有上游依赖已完成的任务会标为readytask_get读取完整任务详情;task_update前应先读取最新状态task_update支持改字段、改状态、添加addBlocks/addBlockedBy,并双向维护依赖task_update的status=deleted会删除任务,同时清理其他任务中的依赖引用
会话级临时便签,给模型一张"便签纸"跟踪短小临时任务。不是默认模式,需要时通过 /tasks todo 切换。
todo_write 的输入是完整 todo 列表,每次调用都会全量替换旧列表。TodoItem 只有三个字段:
| 字段 | 说明 |
|---|---|
content |
祈使句任务描述,例如"运行测试" |
status |
pending / in_progress / completed |
activeForm |
当前进行时文案,例如"正在运行测试" |
设计约束:
- 没有
id字段,避免模型在多轮对话中记错合成标识符 - 通常保持恰好一个任务为
in_progress - 当所有任务都标记为
completed时,清单会自动清空 - Task V2 与 TodoWrite V1 互斥:Task 模式只暴露
task_*工具,Todo 模式只暴露todo_write - Plan Mode 下也允许
todo_write,因为它只写会话状态,不修改文件或环境
| 命令 | 说明 |
|---|---|
/tasks |
查看当前任务系统和任务列表 |
/tasks task |
切回 Task V2 持久化任务图 |
/tasks todo |
切到 TodoWrite V1 兼容模式 |
/tasks reset |
清空当前 session 的任务图,保留 .highwatermark |
/todos |
查看当前会话任务清单 |
/todos clear |
清空当前会话任务清单 |
Skills 用 Markdown 描述可复用工作流,适合代码审查、提交辅助、排障流程等"多步套路"。q-code 启动时只把每个可见 Skill 的 name + description 注入 <system-reminder>,不会把完整 SKILL.md 正文塞进 system prompt;模型调用 Skill 工具或用户输入 /<skill-name> args 时,才按需读取正文并继续本轮推理。
目录:
~/.q-code/skills/<name>/SKILL.md # 用户级,跨项目共享
~/.agents/skills/<name>/SKILL.md # 用户级,跨项目共享;同名覆盖 ~/.q-code/skills
<cwd>/.q-code/skills/<name>/SKILL.md # 项目级,仅当前仓库;同名覆盖用户级
<cwd>/.agents/skills/<name>/SKILL.md # 项目级,仅当前仓库;同名优先级最高
支持的 frontmatter:
| 字段 | 说明 |
|---|---|
name |
Skill 名称,默认目录名 |
description |
discovery 列表中的一行简介;缺失时取正文第一段 |
when_to_use |
何时使用该 Skill 的提示,会追加到简介 |
allowed-tools |
兼容字段,当前 q-code 无权限系统,仅解析保留 |
argument-hint |
/skills 展示的参数提示 |
disable-model-invocation |
为 true 时不出现在模型可见列表,只能用户用 /<name> 触发 |
paths |
gitignore 风格路径;命中 read_file / write_file / edit_file / glob 后条件激活 |
正文变量会在调用时替换:$ARGUMENTS、${Q_CODE_SKILL_DIR}、${Q_CODE_SESSION_ID};同时兼容 Claude Code 风格的 ${CLAUDE_SKILL_DIR}、${CLAUDE_SESSION_ID}。
| 命令 | 说明 |
|---|---|
/skills |
查看已加载 Skills、来源和状态 |
/<skill-name> args |
用户直接触发 Skill |
SubAgent 用于把搜索重、上下文噪音大的聚焦任务交给独立子 Agent。子 Agent 从一条全新的 user message 开始,使用经过过滤的工具集运行同一套 Agent Loop,最后只把简洁摘要通过 Agent 工具返回给主 Agent。短结果会保持内联;长 finalText 会写入 artifact 文件,主上下文、后台通知和 subagent_stop Hook 只接收 preview、字符数、截断标记和恢复路径。
内置角色:
| Agent | 说明 |
|---|---|
general-purpose |
默认通用子 Agent,适合需要多次工具调用的聚焦子任务 |
Explore |
只读探索 Agent,只保留只读工具,适合定位文件、追踪调用和梳理实现模式 |
自定义 Agent 文件:
~/.q-code/agents/<name>.md # 用户级,跨项目共享
<cwd>/.q-code/agents/<name>.md # 项目级,仅当前仓库;同名覆盖用户级
格式:
---
name: reviewer
description: Use for focused code review of a small change set.
tools: 'read_file,grep,glob'
disallowedTools: 'write_file,edit_file'
model: 'gpt-5.4'
maxTurns: 12
isolation: worktree
---
You are a focused code review sub-agent. Return findings first, then residual risk.字段说明:
| 字段 | 说明 |
|---|---|
name |
Agent 工具中的 subagent_type |
description |
discovery 列表里的使用时机说明 |
tools |
可选 allow-list;缺省或 * 表示继承父工具池 |
disallowedTools |
可选 deny-list;即使 tools: "*" 也会剔除 |
readOnlyOnly |
为 true 时只保留 isReadOnly 工具 |
model |
可选模型覆盖;缺省继承父 Agent 默认模型 |
maxTurns |
子 Agent 最大循环步数,缺省 30 |
isolation |
默认隔离级别:none 或 worktree |
Agent 工具参数:
| 参数 | 说明 |
|---|---|
prompt |
必填,自包含任务说明;子 Agent 看不到主对话历史 |
description |
必填,短任务名,用于日志和结果摘要 |
subagent_type |
可选,目标 Agent 类型,缺省 general-purpose |
model |
可选,本次调用模型覆盖 |
run_in_background |
可选,为 true 时后台运行并立即返回 <async_launched> |
isolation |
可选,本次调用隔离覆盖:none / worktree;优先级高于 Agent 定义 |
结构性约束:
- 子 Agent 永远拿不到
Agent工具,避免递归分发 - 子 Agent 永远拿不到
enter_plan_mode/plan_write/exit_plan_mode,避免子任务反向修改父会话模式 Explore使用readOnlyOnly,会剔除写文件、shell、任务写入等非只读工具- 同步 SubAgent 会按解析后的实际工具集动态调度:只包含
isReadOnly工具时允许并行;包含写入工具或使用 worktree 隔离时仍串行,避免并发改动同一工作区 - 子 Agent 不继承主对话历史;传给
Agent.prompt的内容必须自包含 - 长 SubAgent 最终结果不会完整注入主上下文;需要完整内容时按返回的
artifact_file或.output路径用read_file恢复 - 新增或修改自定义 Agent 文件后需要重启 q-code
run_in_background: true 会让 Agent 工具立即返回 <async_launched>,其中包含 agent_id 和 .output 文件路径。后台子 Agent 使用独立 AbortController 继续运行,不会阻塞主对话。运行过程中会把进度写入 JSONL:
.sessions/projects/<projectKey>/async-agents/<sessionId>/<agentId>.output
常见事件包括 started、text、tool_use、tool_result、turn_usage、completed、failed。后台任务完成、失败或被终止后,会进入 pending notification 队列;下一轮用户输入开始前,q-code 会把 <task-notification> 注入对话,让主 Agent 继续基于结果工作。
同步和后台 SubAgent 的长最终产物会写入:
.sessions/projects/<projectKey>/agent-artifacts/<sessionId>/<agentId>.final.md
短结果仍在 <sub_agent_result> 或 <task-notification><result> 中内联;长结果改为 <sub_agent_result_preview> 或 <result_preview>,并包含 artifact_file、original_chars、result_truncated 和恢复说明。subagent_stop Hook 对短结果继续提供 finalText;长结果只提供 finalTextPreview、artifactFile、originalChars、resultTruncated 和 recoveryHint,避免外部命令或 webhook 被大 payload 撑爆。
在默认 TUI 中输入 /agents 会打开交互式 SubAgent Monitor,而不是只打印静态文本。列表视图展示同步/后台 SubAgent 的 ID、执行模式、状态、描述、最近工具、工具次数、token、耗时和 worktree branch;成功完成的 completed SubAgent 默认从终端列表隐藏,失败和终止条目会保留用于排障。按 Enter 进入详情后会 tail 对应 .output JSONL 并格式化工具调用、文本输出、usage、完成或失败信息。详情视图支持 ↑/↓ 上下滚动、End 回到底部,Esc 从详情返回列表、再返回主对话;打开/关闭面板不会清空底部输入内容。当前轮次忙碌且存在 running SubAgent 时,底部会提示可按 Ctrl+A 打开/关闭 SubAgent Monitor,方便等待输出期间直接查看子 Agent 进度。
停止和清理操作也可以直接在 TUI 中完成:列表或详情按 x 会请求终止当前选中的后台 running SubAgent;同步 foreground SubAgent 只能随当前主轮次用 Ctrl+C 中断。列表里按 c 会清理已成功 completed 的 SubAgent 条目;列表里按 Ctrl+X 后再按 Ctrl+K 会进入“停止全部后台 running SubAgent”的二次确认。classic / 非 TTY 环境仍保持文本输出;TUI 下如需强制打印文本列表,可用 /agents list。
isolation: "worktree" 会为本次子任务创建独立 Git worktree:
<gitRoot>/.q-code/worktrees/<agentId>/
子 Agent 的文件读写、Shell、grep/glob 和记忆写入都会相对该 worktree 执行。任务结束时,q-code 会检查 worktree 是否有未提交改动或新 commit:干净则自动移除;有改动或检查失败则保留,并在结果或通知里返回 worktree_path 和 worktree_branch,方便人工 review 或合并。若当前目录不在 Git 仓库内,worktree 创建失败会降级为无隔离并返回 warning。
| 命令 | 说明 |
|---|---|
/agents |
TUI 打开 SubAgent Monitor;classic 打印文本列表 |
/agents list |
强制打印已加载 SubAgents、运行条目、输出和 worktree |
/agents kill <id> |
请求终止运行中的后台 SubAgent |
/agents clear-completed |
清理已成功完成的 SubAgent 条目 |
Agent Teams 在 SubAgent 的基础上增加了网状通信:teammate 之间可以直接 SendMessage 互相对齐,不必把每条消息都中转给 lead;适合需要长期并行、跨角色协作的复杂任务(如 backend + frontend + reviewer 同时推进一个特性)。
启用:用 --agent-teams 启动 q-code 或设置 Q_CODE_TEAMS=1。关闭状态下三个团队工具完全不向模型暴露。
核心模型:
~/.q-code/teams/<team>/
├── team.json ← TeamFile(成员注册表 + lead 信息)
└── inboxes/
├── backend.json ← backend 的收件箱
├── frontend.json ← frontend 的收件箱
└── team-lead.json ← lead 的收件箱
每个进程同一时间只能领导一个团队(teamContext 单例约束);teammate 不能再嵌套 TeamCreate 或派出二级 teammate。
三个工具:
| 工具 | 作用 |
|---|---|
TeamCreate |
开启团队会话,把当前进程注册为 lead |
SendMessage |
把纯文本消息丢进收件人的收件箱(to: "*" 广播;自发自收会被拒绝) |
TeamDelete |
解散团队,删 team.json + 所有 inbox + 干净 worktree(脏 worktree 保留);要求所有 teammate 已 idle |
Agent 工具的扩展:原有 Agent({ ... }) 增加可选参数 name + team_name:
Agent({
subagent_type: 'general-purpose',
name: 'backend',
team_name: 'refactor-auth',
run_in_background: true,
prompt: '实现 /api/auth 的 JWT 认证',
description: '后端认证模块'
})文档要求的 7 条校验全部覆盖:
| 校验 | 错误信息 |
|---|---|
name 但 Agent Teams 未启用 |
Agent Teams feature is not enabled |
只传 name 或只传 team_name |
name and team_name must be used together |
| 没有活跃团队 | no team is active |
team_name 与活跃团队不一致 |
team_name does not match active team |
name 等于保留字 team-lead |
team-lead is reserved |
| 调用者本身已是 teammate(嵌套) | nested teammate spawn rejected |
run_in_background 不为 true |
named teammates must run in background |
通信流:teammate 启动时 runChildAgent 会先 drainUnreadMessages 把所有未读邮件以 <teammate-messages> 上下文块拼到第一条 user prompt 前面;teammate 终止(成功/失败/被 kill)时 runAsyncAgent 在 finally 块里把 isActive 翻成 false,<task-notification> 在下一轮用户输入前注入对话。
System prompt 三档:
| 状态 | 注入内容 |
|---|---|
| 特性开关关闭 | 空字符串 |
| 开启但无团队 | 提示模型 TeamCreate 的使用时机 |
| 已有活跃团队 | 完整 roster(active/idle)+ 工作流规则 |
| 命令 | 说明 |
|---|---|
/teams |
查看活跃团队、成员状态、磁盘上的所有团队目录 |
/teams clear |
清理当前团队(要求无活跃 teammate) |
/teams clear force |
强制清理(建议先 /agents kill <agent_id>) |
q-code 支持标准 mcpServers 配置,把外部 MCP server 适配成普通工具。配置分两级:
| 路径 | 说明 |
|---|---|
~/.q-code/settings.json |
全局 MCP 配置;可通过 Q_CODE_HOME 改变根目录 |
<cwd>/.q-code/settings.json |
项目级 MCP 配置;同名 server 整条覆盖全局配置 |
示例:
{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "."]
},
"github": {
"type": "http",
"url": "https://api.githubcopilot.com/mcp/",
"headers": {
"Authorization": "Bearer <token>"
}
}
}
}支持的 transport:
| 类型 | 说明 |
|---|---|
stdio |
默认类型;本地子进程,如 npx -y @modelcontextprotocol/server-* |
http |
Streamable HTTP;适合远端 SaaS / 自建服务 |
sse |
旧版 SSE;headers 会同时注入 POST 和长连 GET |
MCP 工具名会规范化为 mcp__<server>__<tool>,例如 my.db 的 echo.tool 会变成 mcp__my_db__echo_tool。MCP 工具默认延迟加载,Agent 需要时通过 tool_search 按需激活,避免大量外部工具撑大 System Prompt。
启动时 MCP 连接在后台并行进行:慢 server 不会阻塞 CLI;连接成功后工具会增量注册。--dump-system-prompt 会等待 MCP bootstrap 完成,方便检查最终 prompt。
兼容说明:如果未配置 mcpServers.github,但设置了 GITHUB_PERSONAL_ACCESS_TOKEN,q-code 会按旧行为自动添加一个 GitHub stdio MCP server。新项目建议迁移到 settings.json。
| 命令 | 说明 |
|---|---|
/mcp |
查看 MCP server 状态、transport、工具数量 |
/mcp tools <serverName> |
查看某个 server 暴露的工具 |
/mcp reconnect <serverName> |
清理缓存并重连某个 server |
企业 AI 基建是可选集成功能,默认关闭。只有显式配置 Q_CODE_INFRA_ENABLED=true 后,q-code 才会读取 Q_CODE_INFRA_BASE_URL 和 Q_CODE_INFRA_TOKEN,并在启动时向企业配置中心解析当前仓库所属业务域,再把配置包增量写入本地项目:
<cwd>/.q-code/settings.json # 企业 MCP server 配置
<cwd>/.q-code/skills/<name>/ # 云端下发 Skills
<cwd>/.q-code/infra-state.json # 最近一次同步状态
<cwd>/AGENTS.md # 企业规则受管区块
未开启 Q_CODE_INFRA_ENABLED 时,q-code 不会写入任何企业配置文件,原有本地行为保持不变。开启后若配置中心不可用,Client 会保留最近一次成功状态,并在 /infra status 中标记为 stale 或 failed。
| 命令 | 说明 |
|---|---|
/infra |
查看企业配置同步状态,等价于 /infra status |
/infra status |
查看业务域、配置包版本、本地写入路径和错误 |
/infra sync |
手动重新拉取配置;若配置变化会刷新 MCP 连接 |
GitLab Wiki 知识库是一个可选外部集成。配置 GitLab URL 和 Token 后,q-code 会把当前仓库对应的 GitLab Project Wiki 当作企业内部知识共享载体:团队成员只要拥有该项目 Wiki 的访问权限,就能共享仓库级 FAQ、排障结论、工程约定和架构决策。
推荐在全局或项目 .q-code/config.toml 中配置:
[gitlab_kb]
url = "https://gitlab.example.com/group/project"
token = "glpat-..."
prefix = "q-code-kb"url 可以是 GitLab 实例地址,也可以是项目地址;如果没有显式配置 project_id,q-code 会优先从项目地址推断,再尝试从当前仓库 remote.origin.url 推断。默认只读写 q-code-kb/ 前缀下的 Wiki 页面,避免和人工维护的 Wiki 首页混在一起。
| 命令 | 说明 |
|---|---|
/gitlab-kb 或 /kb |
查看配置和项目解析状态 |
/gitlab-kb list [关键词] |
列出或搜索知识页 |
/gitlab-kb get <slug> |
读取单个 Wiki 知识页 |
/gitlab-kb publish --title "标题" [--slug slug] <正文> |
发布或更新知识页 |
配置后模型也会按需获得 gitlab_kb_search、gitlab_kb_read、gitlab_kb_publish 三个延迟工具;未配置时这些工具不会暴露给模型。
采用 JSONL append-only 格式存储在 .sessions/projects/<projectKey>/<sessionId>.jsonl,支持:
--continue恢复最近一次会话--session=<id>指定会话 ID- 崩溃恢复:逐行解析,损坏行跳过
- 压缩快照全量写入,恢复时从最后快照后加载
每个会话会同步维护 .sessions/projects/<projectKey>/<sessionId>.meta.json,记录展示名、创建/更新时间、消息数、tokens、首条用户输入摘要、模型和 tags。老会话没有 meta 时,/sessions 首次列表会从 JSONL 自动回填。
TUI 内可直接使用 /sessions 管理会话,不需要重启进程:
| 命令 | 说明 |
|---|---|
/sessions 或 /sessions list [--all] |
列出最近会话;TUI 中可用 ↑/↓ 选择并 Enter 切换 |
/sessions info [<id>] |
查看当前或指定会话详情 |
/sessions switch <id> |
不重启进程切换到指定会话 |
/sessions new ["<displayName>"] |
新建会话并立即切换 |
/sessions rename <id> "<name>" |
修改展示名 |
/sessions delete <id> [--force] |
默认软删到 .trash;--force 物理删除 |
/sessions restore <id> |
从 .trash 恢复 |
| `/sessions export [--format md | json |
/sessions search <keyword> [--all] |
跨会话搜索 user/assistant 文本 |
/sessions purge [--older-than 30d] |
预览并确认清理过期 trash 会话 |
q-code 内置跨对话持久化的项目记忆,让 Agent 能在多次对话间保留和检索关键信息。
存储结构:
.sessions/projects/<projectKey>/memory/
├── MEMORY.md # 索引文件(自动维护)
├── deploy-rules.md # 主题记忆文件
└── api-conventions.md # 主题记忆文件
每个记忆文件使用 YAML frontmatter 格式:
---
name: 部署规则
description: 生产环境部署注意事项
type: project
---
正文内容...索引文件 MEMORY.md 是自动维护的索引,不保存完整正文,只包含指向各主题文件的链接:
# Project Memory
- [部署规则](deploy-rules.md) — 生产环境部署注意事项
- [API 约定](api-conventions.md) — REST API 命名与版本规范索引上限:200 行 / 25000 bytes,超出自动截断。
记忆类型:
| 类型 | 说明 |
|---|---|
user |
用户长期偏好、协作方式、目标或角色信息 |
feedback |
用户对执行方式、质量标准、注意事项的长期反馈 |
project |
不能直接从仓库推导的项目约束、背景、决策 |
reference |
外部系统、仪表盘、文档、工单或数据源位置 |
写入记忆:Agent 通过 memory_write 工具写入记忆,支持新建和更新已有文件(按 name/description 匹配)。
读取记忆:Agent 启动时,记忆索引自动注入 System Prompt。当用户提到历史约定或相关主题时,Agent 会主动 read_file 读取对应记忆文件。
记忆边界:
- 会话历史保存一次对话过程;项目记忆只沉淀跨对话仍然成立的信息
- 不保存能从仓库直接读取的内容(代码结构、文件内容等)
- 不保存 git 已能表达的信息(提交历史、diff 等)
- 不保存一次性调试过程或临时计划
- 使用记忆前应先验证当前状态,记忆与实际冲突时以验证为准
忽略记忆:用户输入包含 "忽略记忆" / "ignore memory" 等关键词时,本轮对话不应用任何已保存记忆。
q-code 把测试拆成两层:Vitest 单元/集成测试(生产可用、覆盖率友好)+ Legacy 端到端脚本(单文件 tsx 直跑、面向真实模块联调)。
tests/
├── _helpers/ # 共享测试基础设施
│ ├── mock-model.ts # 基于 MockLanguageModelV3 的脚本化模型
│ ├── mock-tool.ts # makeMockTool / makeRecordingTool / makeFlakeyTool
│ └── temp-home.ts # 隔离 Q_CODE_HOME 的 fixture
├── unit/ # 纯函数 + 模块级单元测试
│ ├── atomic-write.test.ts
│ ├── retry.test.ts
│ ├── loop-detection.test.ts
│ ├── tool-registry.test.ts
│ └── prompt-builder.test.ts
└── integration/ # 跨模块集成 + 真实文件系统
├── agent-loop.test.ts # mock model 驱动 ReAct 循环
├── session-recovery.test.ts
├── session-switch.test.ts
├── task-graph.test.ts
└── team-flow.test.ts
src/evals/ # q-code eval 本地评测框架
├── loader.ts # 读取 evals/**/*.yaml|json
├── runner.ts # mock-agent / cli-subprocess / real-agent runner + artifact 输出
├── trace-recorder.ts # agentLoop 回调转 JSONL trace
├── judge.ts # opt-in LLM-as-judge scorer
├── scorers.ts # final/trajectory/budget/safety/tool/side-effect scorer
├── langfuse-api.ts # Langfuse dataset run items / scores Public API bridge
├── langfuse-export.ts # 可选 Langfuse evaluator trace 导出
└── trend.ts # 本地趋势看板 JSON/Markdown
| 命令 | 用途 |
|---|---|
pnpm test |
跑所有 vitest 单元 + 集成测试(默认 CI 入口) |
pnpm test:watch |
watch 模式开发 |
pnpm test:coverage |
生成 v8 覆盖率报告(HTML + lcov) |
pnpm test:unit |
仅跑 tests/unit |
pnpm test:integration |
仅跑 tests/integration |
pnpm test:legacy |
跑 src/scripts/test-*.ts 全套端到端脚本 |
pnpm test:all |
vitest + legacy 全部 |
pnpm typecheck |
tsc --noEmit 全项目类型检查 |
pnpm eval:smoke |
运行 deterministic smoke eval,不导出 Langfuse |
pnpm eval:cli |
运行 cli-subprocess fixture eval,不导出 Langfuse |
pnpm eval:ci |
运行 smoke + cli eval,并输出 JUnit 报告 |
pnpm eval:smoke:langfuse |
运行 smoke eval 并导出到配置的 Langfuse |
pnpm eval:nightly |
运行定期 deterministic 回归并生成趋势看板 |
pnpm eval:trend |
从历史 eval runs 生成本地趋势看板 |
pnpm eval:compare |
对比两个 eval run |
pnpm prompt:cache:verify |
本地验证稳定 system prompt hash 与 90%+ 前缀目标 |
| 主题 | 测试位置 |
|---|---|
| 文件原子性 | unit/atomic-write.test.ts — 100 次顺序 + 50 次并发零 tmp 残留 |
| 重试退避 | unit/retry.test.ts — 指数退避边界 + 错误分类 |
| 死循环防护 | unit/loop-detection.test.ts — 三种检测器三档阈值 |
| 并发锁 | unit/tool-registry.test.ts — 独占/共享锁、cwd/abort/identity 透传 |
| Prompt 管道 | unit/prompt-builder.test.ts — pipe 顺序、空跳过、各内置 pipe 字段透传 |
| Agent ReAct 循环 | integration/agent-loop.test.ts — mock 模型 + mock 工具的多步 ReAct + abort |
| 会话恢复/切换 | integration/session-recovery.test.ts / integration/session-switch.test.ts — 损坏 JSONL 行恢复、压缩快照分界、无重启切换 |
| 任务图 | integration/task-graph.test.ts — CRUD + 双向依赖 + reset 不复用 id |
| Agent Teams | integration/team-flow.test.ts — 完整流程 + reconcile + 并发邮箱 + 大小限制 |
| Agent Eval | unit/evals.test.ts — 加载 smoke/cli/live case、运行 runner、生成 trace、报告、judge 解析、趋势看板和副作用 artifact |
写新集成测试时,引入 tests/_helpers/:
import { agentLoop } from '../../src/agent/loop'
import { ToolRegistry } from '../../src/tools/registry'
import { createMockModel } from '../_helpers/mock-model'
import { makeRecordingTool } from '../_helpers/mock-tool'
const { tool, calls } = makeRecordingTool('probe', '工具结果')
const registry = new ToolRegistry({ cwd: '/tmp', quiet: true })
registry.register(tool)
const { model } = createMockModel([
{ tools: [{ name: 'probe', input: { foo: 1 } }] },
{ text: '完成', finishReason: 'stop' }
])
await agentLoop(model, registry, [{ role: 'user', content: 'go' }], 'sys', {
quiet: true
})createMockModel(turns) 接收一个脚本数组,每一项描述一次 streamText 调用应该输出什么;如果脚本耗尽,会自动产生一个空 stop 轮让循环优雅退出。
| 触发 | 命令 | 耗时 | 内容 |
|---|---|---|---|
本地 git commit |
pnpm precommit |
~6 秒 | typecheck + 单元测试(tests/unit/**) |
| GitHub Actions(push / PR) | .github/workflows/ci.yml |
~1-2 分钟 | typecheck + vitest 全部 + legacy 端到端 |
仓库使用 simple-git-hooks(零运行时依赖、配置写在 package.json)。pnpm install 时会通过 prepare 脚本自动把 hook 安装到 .git/hooks/pre-commit,每次 commit 前会自动跑:
pnpm typecheck && pnpm test:unit跳过 hook(仅紧急时使用):
SKIP_SIMPLE_GIT_HOOKS=1 git commit -m "..."或者:
git commit -n -m "..." # 等同于 --no-verify为什么 pre-commit 只跑单元测试:
- 集成测试要起 git worktree 和真实 fs,几秒到 30 秒不等,pre-commit 太重
- 单元测试 + typecheck 已能挡掉 90% 的明显 bug,留下的让 CI 兜底
- 节省的等待时间 = 更频繁的小提交 = 更好的 git 历史
.github/workflows/ci.yml 在 push main 与 pull_request to main 时触发,按以下顺序跑:
pnpm typecheckpnpm test(vitest 单元 + 集成)pnpm test:legacy(5 套端到端脚本)
并发策略:同一分支推新 commit 自动取消上一轮 CI(concurrency + cancel-in-progress)。
在项目目录或 ~/.q-code/ 下放置 AGENT.md 或 AGENTS.md,内容会作为项目级指令注入 System Prompt。加载顺序:
~/.q-code/AGENT.md— 全局指令- 项目根目录到当前目录的链式加载
- 冲突时,路径越接近当前目录的优先级越高
System Prompt 由 PromptBuilder 按管道顺序拼接,每个 Pipe 可根据上下文动态开关:
| Pipe | 稳定性 | 说明 |
|---|---|---|
coreRules |
stable |
核心行为准则 |
agentMdInstructions |
stable |
AGENT.md 项目指令 |
toolDiscipline |
stable |
不含工具数量/JIT 摘要的稳定工具纪律 |
skillDiscipline |
stable |
不含当前 Skill 列表的稳定调用纪律 |
agentsContext |
stable |
SubAgents discovery 提醒 |
deferredToolDiscipline |
stable |
不含具体列表的稳定 tool_search 纪律 |
每轮用户输入时,buildSystemPrompt(userQuery) 只重建稳定 system prompt;本轮动态内容由 buildTurnContextTransientMessages(...) 汇总到尾部 user context。该 transient context 包含 toolRuntimeSummary、当前延迟工具列表、当前可见 Skill 列表、teamsContext、modeContext、Task/Todo 上下文、runtimeEnvironment、projectMemory、sessionContext 和长报告流式提示。它参与本轮模型请求和上下文预算估算,但不会写入会话历史或压缩快照。
.sessions/projects/<projectKey>/
├── <sessionId>.jsonl # 会话持久化 (JSONL)
├── async-agents/
│ └── <sessionId>/
│ └── <agentId>.output # SubAgent JSONL 进度输出
├── agent-artifacts/
│ └── <sessionId>/
│ └── <agentId>.final.md # SubAgent 长 finalText 完整产物
├── plans/
│ └── <sessionId>.md # 计划文件
├── tasks/
│ └── <sessionId>/
│ ├── 1.json # 任务文件
│ ├── 2.json
│ └── .highwatermark # ID 高水位
└── memory/
├── MEMORY.md # 记忆索引
└── <topic>.md # 主题记忆文件
~/.q-code/ (或 Q_CODE_HOME)
├── settings.json # 全局 MCP 配置
├── AGENT.md # 全局项目指令
├── skills/<name>/SKILL.md # 用户级 Skills
├── agents/<name>.md # 用户级自定义 Agents
├── history/global.jsonl # 全局 TUI 输入历史
├── shell-spills/<jobId>.log # f 同步超大输出 spill
└── shell-jobs/<sessionId>.index# f 后台 job 元数据索引
~/.agents/skills/<name>/SKILL.md # 用户级 Skills(覆盖 ~/.q-code/skills 同名 Skill)
<cwd>/.q-code/
├── settings.json # 项目级 MCP 配置
├── AGENT.md # 项目级指令
├── file-mention-index.json # TUI @file 候选索引缓存
├── history.jsonl # 项目级 TUI 输入历史
├── skills/<name>/SKILL.md # 项目级 Skills
├── agents/<name>.md # 项目级自定义 Agents
└── evals/runs/<run-id>/ # 本地 Agent eval artifact(run/cases/report/traces)
<gitRoot>/.q-code/worktrees/
└── <agentId>/ # 后台 Agent worktree 隔离目录
交互式启动默认进入 TUI。快捷键:Enter 发送,Ctrl+J 换行,↑/↓ 切换历史,Ctrl+R 搜索历史,Esc 清空/恢复输入,忙时 Ctrl+C 中断当前任务,空闲时 Ctrl+C 退出。出现 Plan Mode 建议确认条时,Enter 进入 Plan 并继续原请求,Esc 按普通模式执行,Ctrl+C 取消建议。需要旧版纯文本交互时使用 pnpm start -- --classic 或设置 Q_CODE_TUI=0。
TUI 状态栏默认只展示当前状态;需要查看模式、模型、cache 策略、任务系统、context 进度和 token 摘要时使用 /status on 打开详情,/status off 关闭。已完成历史会静态输出,流式输出期间只刷新当前轮,并限制 streaming 预览高度以减少 VSCode 等终端闪烁。执行中会同时保留中间进度旁白和工具调用摘要;等最终回答出现后,已完成工具调用会折叠,只留下对话内容。输入 / 时命令建议按类别分组展示,工具调用默认以一行紧凑摘要呈现,失败时显示恢复建议。
/ya [list|yellow|shanghai|heilongjiang|toggle] 可切换主 Agent 鸭子人格。默认小黄鸭不注入额外提示;主题鸭只作为本轮临时用户消息放在模型请求末尾,不进入 system prompt、会话历史或压缩快照,因此切换鸭子不会改变 /cache 追踪的 system/tools prefix。
TUI 输入历史会跨进程持久化:项目历史写入 <cwd>/.q-code/history.jsonl,全局历史写入 <Q_CODE_HOME>/history/global.jsonl,默认 Q_CODE_HISTORY_SCOPE=both 会同时读取/写入两边并按时间合并去重。空输入、空格开头输入、连续重复输入,以及包含 password= / api_key= / token= 的内容默认不会写入;可在 settings.json 中配置 history.excludePatterns 增加项目或用户级过滤规则,或设置 history.excludeDefaults=false 关闭默认敏感词过滤。Q_CODE_HISTORY_REDACT=true 会把历史文件切换为 SHA-256 + 前 40 字符摘要模式。/history 查看最近 30 条,/history clear [global|project|both] 清空指定作用域,/history off / /history on 可临时暂停或恢复本会话记录。
| 命令 | 说明 |
|---|---|
/context |
查看上下文占用矩阵 |
| `/model [name | default]` |
/models [list] |
根据当前配置列出可用模型(TUI 可选中切换) |
/sessions |
列出/切换/管理会话 |
| `/history [clear | on |
/usage |
查看 token/cache/成本 |
/cost |
/usage 的兼容别名 |
| `/cache [status | auto |
| `/status [on | off |
| `/ya [list | yellow |
/compact [focus] |
手动触发上下文压缩 |
/mode |
查看当前模式 |
/mode plan |
进入 Plan Mode |
/mode normal |
回到 Normal 模式 |
/mode toggle |
切换 Plan / Normal |
/plan |
查看当前计划文件 |
/approve-plan |
批准计划并切回 normal |
/revise-plan <反馈> |
不批准,带反馈继续规划 |
/tasks |
查看当前任务系统 |
/tasks task |
切到 Task V2 |
/tasks todo |
切到 TodoWrite V1 |
/tasks reset |
清空任务图 |
/todos |
查看会话任务清单 |
/todos clear |
清空清单 |
/skills |
查看已加载 Skills |
/<skill-name> args |
触发 Skill |
/agents |
TUI 打开 SubAgent Monitor |
/agents list |
打印已加载 SubAgents |
/agents kill <id> |
终止后台 SubAgent |
/agents clear-completed |
清理已完成 SubAgent |
/infra |
查看企业 AI 基建配置同步状态 |
/infra sync |
手动同步企业配置 |
/gitlab-kb 或 /kb |
查看 GitLab Wiki 知识库状态 |
/gitlab-kb list |
列出/搜索 Wiki 知识页 |
/gitlab-kb get <slug> |
读取 Wiki 知识页 |
/mcp |
查看 MCP 状态 |
/mcp tools <name> |
查看某 server 的工具 |
/mcp reconnect <name> |
重连某 server |
exit |
退出 |
pnpm run test:agents # SubAgents + 后台 Agent + worktree 隔离
pnpm run test:skills # Skills 渐进式披露
pnpm run test:mcp # MCP smoke test
pnpm run eval:smoke # deterministic Agent eval
pnpm run eval:cli # CLI subprocess side-effect eval
pnpm run eval:trend # 生成 eval 趋势看板
pnpm exec tsc --noEmit # TypeScript 类型检查src/下生产模块在文件头提供模块级中文说明;对外导出函数、类、接口、类型与常量配有 JSDoc(行为、边界、副作用以当前实现为准)。- 复杂非显然逻辑辅以少量行内注释(说明「为何」而非复述代码);TUI 组件仅文档化导出符号与关键 props。
- 目录职责与协作约定见仓库根目录
AGENTS.md;API 细节以源码 JSDoc 为准,README 不重复维护完整符号表。
MIT