跳到主要内容

从命令到智能体:入口、Session 与装配

30 秒导读: 你在终端敲下 kimi,回车那一刻发生了什么?这一章把"一次启动"拆成一条装配线:命令行参数怎么被解析、会话(Session)从哪里加载或新建、然后 KimiCLI.create 如何把配置、大模型、运行时、Agent 规格、系统提示、上下文、灵魂(Soul)、钩子、遥测一层层拼起来,最后交给某个 UI 出口去跑。读完你应该能画出这张"启动即装配"的对象图,知道每块零件从哪来。至于装配好之后主循环怎么转——那是下一章的事。

本章属于 Kimi CLI 参考手册。它只讲启动到就绪这一段;不深入主循环内部(见 02)、上下文压缩(03)、工具审批(04)、子智能体(06)。


1. 这是什么:一次启动的鸟瞰

先建立最粗的直觉。Kimi CLI 是一个终端里的编码智能体——你在命令行跟它对话,它读你的代码、跑命令、改文件。而"启动"这件事,本质上是把一堆零散的部件组装成一个能对话的智能体实例

打个比方:启动就像汽车装配线。命令行参数是订单(要什么配置、恢复哪次对话),Session 是底盘(这次对话的持久化身份),KimiCLI.create 是主装配线(把发动机 LLM、控制系统 Runtime、驾驶习惯 Agent 规格逐个装上),最后 run_* 把整车开出不同的门(交互式 shell、一次性 print、ACP/Wire 服务器)。

一次典型启动的高层流水:

kimi -C "帮我修这个 bug"


┌──────────────┐ ┌──────────────┐ ┌──────────────────────┐
│ ① 命令行解析 │──▶│ ② 定位 Session │──▶│ ③ KimiCLI.create 装配 │
│ Typer app │ │ 新建/find/续 │ │ config→LLM→Runtime │
│ 校验冲突参数 │ │ context.jsonl │ │ →Agent→Context→Soul │
└──────────────┘ │ wire.jsonl │ │ →hook→telemetry │
└──────────────┘ └──────────┬───────────┘

┌────────────────────────┐
│ ④ UI 出口(四选一) │
│ shell / print / acp/wire │
└────────────────────────┘
```

四个阶段,本章逐个拆。阶段 ①② 在 cli/__init__.py阶段 ③ 在 app.py:KimiCLI.create,Runtime/Agent 的细节在 soul/agent.pyagentspec.py


2. 阶段①:CLI 入口与子命令

这节讲:从操作系统的 argv 到一个被 Typer 解析好的调用。

2.1 极薄的进程入口

真正的进程入口是 __main__.py:mainsrc/kimi_cli/__main__.py:12)。它刻意做得很薄,只干三件"必须最早做"的事,然后把控制权交给 Typer:

# 示意,非源码;对应 __main__.py:12
def main(argv=None):
install_crash_handlers() # 崩溃钩子要先于一切装上
normalize_proxy_env() # 规整代理环境变量
# 手动截胡 --version,绕开完整解析
if args == ["--version"]:
print(...); return 0
from kimi_cli.cli import cli # 延迟导入,加快冷启动
return cli(args=args, prog_name="kimi")

两个细节值得记住:崩溃处理器(install_crash_handlers)在任何业务代码之前安装__main__.py:17),这样连"启动阶段"的崩溃都能被捕获;--version 被手动短路(__main__.py:22),不必付出完整 CLI 解析的代价。

2.2 Typer 应用与 kimi 主回调

cli 是一个 typer.Typer 实例(cli/__init__.py:40)。它用 invoke_without_command=True 声明了一个主回调 kimicli/__init__.py:77)——意思是"不带子命令直接 kimi ... 时,就执行这个回调"。这个回调就是整个交互式启动的入口,它接收几十个命令行选项。

关键选项按用途分组:

组别选项(节选)作用
会话--session/-S--continue/-C恢复指定会话 / 续上一次会话
模型--model/-m--thinking选模型、开关思考模式
运行模式--yolo/-y--afk--plan全自动批准 / 无人值守 / 计划模式
UI 出口--print--acp--wire切换非交互/协议服务器 UI
定制--agent--agent-file--mcp-config--skills-dir换 agent 规格、挂 MCP、加技能
循环控制--max-steps-per-turn覆盖主循环上限

回调体里最重要的一段逻辑是冲突参数校验cli/__init__.py:435-460):把互斥的选项分组成 conflict_option_sets,任何一组里同时激活两个就报 BadParameter。例如 --print/--acp/--wire 三选一、--continue--session 不能并存。这保证了后面装配拿到的是一组自洽的参数。

校验完,回调把 UI 模式收敛成一个字符串(cli/__init__.py:469-475):默认 "shell",带 --print"print",以此类推。这个 ui 字符串会一路传到装配和出口分发。

2.3 子命令与懒加载

除了主回调,cli 上还挂了若干显式子命令loginlogout(OAuth 登录/登出,cli/__init__.py:904/963)、term(Toad TUI,cli/__init__.py:1007)、acpcli/__init__.py:1017),以及两个隐藏的内部子命令

  • __background-task-workercli/__init__.py:1025)——后台任务的子进程入口,被 06 章的后台任务系统 fork 出来跑。
  • __web-workercli/__init__.py:1053)——web 界面的会话工作子进程。

它们以 hidden=True 声明,不出现在帮助里,只由程序自己以子进程方式调用。

懒加载子命令组 是这里的巧妙处。像 mcppluginwebvisexportinfo 这些"重"子命令,导入它们会拖慢冷启动。于是 cli 用了自定义的 LazySubcommandGroupcli/_lazy_group.py:13),把这些子命令登记成一张 (模块, 属性, 说明) 的映射表(_lazy_group.py:16-23),只有真正调用某个子命令时才 import_module 加载它

# 示意,非源码;对应 _lazy_group.py:56-69 get_command
def get_command(self, ctx, cmd_name):
if cmd := super().get_command(ctx, cmd_name): # 已注册的直接返回
return cmd
spec = self.lazy_subcommands.get(cmd_name) # 查懒加载表
if spec is None:
return None
module_name, attr, _ = spec
cmd = get_command(getattr(import_module(module_name), attr)) # 现用现导
self.commands[cmd_name] = cmd # 缓存
return cmd

这个类还顺手处理了一个 Typer/Click 的边角:--session不跟值时要落到"交互式挑会话"模式,靠 make_context 里把 session_id 选项标记为 _flag_needs_value_lazy_group.py:40-47)实现——这样 -S 单独出现时返回空串 "",回调据此进入 picker 模式(见 2.4)。

2.4 会话 ID 的三态

主回调开头对 session_id 做了三态区分cli/__init__.py:410-418),这是理解"新建 vs 恢复 vs 挑选"的关键:

session_id含义
None没给 --session → 新会话
""(空串)给了 -S 但没带 ID → picker 模式,交互式列出会话让你挑
"某个ID"恢复这个具体会话

picker 模式(cli/__init__.py:811-846)会用 Session.list 列出该工作目录下所有会话,配 ChoiceInput 让你上下选,选完把结果塞回 session_id,再进入正常的启动流程。


3. 阶段②:会话持久化(Session)

这节讲:一次对话的"身份"如何在磁盘上存续,Session 对象怎么被创建、查找、续接。

3.1 Session 是什么

Sessionsession.py:22)是一个 dataclass,代表某个工作目录下的一次对话。它把这次对话的所有持久化零件聚在一起:

字段是什么
id会话 UUID
work_dir绝对工作目录路径(KaosPath)
work_dir_meta该工作目录的元数据(含 sessions 存储路径、last_session_id
context_filecontext.jsonl 的路径——消息历史检查点
wire_filewire.jsonl 的封装——UI 事件流日志
stateSessionState——审批设置、计划模式、附加目录、todo 等
title / updated_at可刷新的展示元数据

为什么是两个 JSONL? 这是 Kimi CLI 的一个重要设计(细节见 03 章):

  • context.jsonlsession.py:150)= 发给模型的消息历史,一行一条记录。含系统提示、user/assistant 消息、工具结果。这是"给 LLM 看的真相"。
  • wire.jsonlsession.py:175)= 给 UI 看的事件流,记录一次次 turn、渲染事件。会话标题就是从这里第一条 TurnBegin 的用户输入里提取的(session.py:114-122)。

两者分离让"喂模型的上下文"和"给人看的界面回放"各自独立演化。

3.2 磁盘布局

会话不存在项目目录里,而是存在用户主目录的共享区。get_share_dir()share.py:7)默认是 ~/.kimi(可被 KIMI_SHARE_DIR 覆盖)。每个工作目录按其路径的 md5 散列出一个子目录(metadata.py:34-40sessions_dir),避免不同项目撞名:

~/.kimi/
├── kimi.json # 全局 Metadata:所有 work_dir + 各自 last_session_id
├── logs/kimi.log # 日志(enable_logging 写入,app.py:61)
└── sessions/
└── <md5(work_dir)>/ # 每个工作目录一个散列目录
└── <session-uuid>/ # 每次会话一个目录(session.py:49 dir)
├── context.jsonl # 消息历史检查点
├── wire.jsonl # UI 事件流
├── state.json # SessionState(session_state.py:12)
└── subagents/ # 子智能体实例(session.py:56)
```

kimi.json 里的 WorkDirMeta.last_session_idmetadata.py:30)记录每个工作目录"最近一次会话",--continue 就靠它找回上次对话。

3.3 四种加载路径

Session 用四个静态/类方法覆盖所有加载场景,主回调的 _runcli/__init__.py:544)按参数分派:

方法触发干什么
Session.create默认(无 -S/-C新建 UUID、建目录、touchcontext.jsonlsession.py:129
Session.find--session ID按 ID 找目录,找不到就退回 createsession.py:183;调用点 cli/__init__.py:558-565
Session.continue_--continuelast_session_id,再 findsession.py:287
Session.listpicker 模式列出所有非空会话,按更新时间倒序(session.py:226

一个体贴的细节:Session.find 到一个存在的会话时,只有当 wire_file 非空才算真正 "resumed"(cli/__init__.py:567-570)——像 /new/undo 造出的 turn-0 空会话虽有目录却当作全新启动,避免误报"已恢复"。

3.4 迁移:版本演进的兼容层

代码里散落着两处向后兼容迁移,是长期项目的典型痕迹:

  • 会话目录迁移_migrate_session_context_filesession.py:309)把老版的扁平文件 <id>.jsonl 搬进新版的 <id>/context.jsonl 目录结构。find/list 每次都顺手触发。
  • 状态字段迁移_migrate_legacy_metadatasession_state.py:50)把早期存在独立 metadata.json 里的标题/归档字段,一次性并进 state.jsonSessionState,成功后删掉旧文件。

SessionStatesession_state.py:28)本身是个带 version 字段的 Pydantic 模型,损坏时静默回退到默认值并打点遥测(session_state.py:107-112),保证坏一个状态文件不会让启动崩掉。


4. 阶段③:核心装配 KimiCLI.create

这是全章的心脏。KimiCLI.createapp.py:121)是一条顺序装配线:拿到一个 Session,逐步产出一个完全就绪的 KimiCLI 实例。它的返回物只包了三样:soulruntime、环境覆盖信息(app.py:377)。

4.1 装配九步

按代码顺序,装配是这样一步步长出来的(每步旁标了源码锚点):

KimiCLI.create(session, ...) app.py:121

1. load_config ────────────── 读 ~/.kimi/config.toml app.py:196
│ └─ CLI 覆盖 loop_control 上限 app.py:198-203
2. OAuthManager(config) ───── 建 OAuth 管理器 app.py:207
│ └─ 后台异步刷新托管模型列表 app.py:209
3. 选 model / provider ────── 从 config 或环境变量决定 app.py:214-231
│ └─ 没配到就给空占位(未登录也能起) app.py:224-226
4. create_llm ────────────── 造 LLM 客户端 app.py:243
5. Runtime.create ────────── 造运行时容器(下节详解) app.py:258
│ └─ 恢复通知、对账后台任务、清理僵尸子智能体 app.py:270-272
6. load_agent ────────────── 读 agent.yaml + 系统提示 app.py:295
│ └─ 装工具、注册子智能体、(延迟)挂 MCP soul/agent.py:383
7. Context.restore ───────── 从 context.jsonl 回放历史 app.py:305-306
│ └─ 恢复过就沿用旧系统提示,否则写入新的 app.py:308-311
8. KimiSoul(agent, context) ─ 造"灵魂"(主循环载体) app.py:313
│ └─ 计划模式激活 / 提醒 app.py:316-320
9. HookEngine + telemetry ── 装钩子引擎、初始化遥测 app.py:323-352
└─ 打点 started / startup_perf app.py:363-375
```

几个关键取舍:

  • 未登录也能启动。 第 3 步选不到模型时不报错,而是塞一个空的 LLMModel/LLMProvider 占位(app.py:224-226)。于是你没登录也能进 shell,界面会提示"send /login to login"(app.py:730-737)。
  • 不阻塞在网络上。 托管模型刷新是 asyncio.create_task 甩到后台的(app.py:209),启动不等它;它的句柄 bg_refresh_task 会被存进实例,退出时取消(app.py:416)。
  • MCP 可延迟加载。 交互式 shell 且无预设 prompt 时,defer_mcp_loading=Truecli/__init__.py:636),MCP 工具的连接推迟到 shell 就绪后再做,让界面先亮起来(细节见 04 章)。

4.2 系统提示的复用规则

第 7-8 步之间有个容易忽略但重要的规则(app.py:305-311):

# 示意,非源码;对应 app.py:305-311
context = Context(session.context_file)
await context.restore() # 回放历史,可能读出旧系统提示
if context.system_prompt is not None:
# 恢复的会话:沿用当初落盘的系统提示,保证前后一致
agent = dataclasses.replace(agent, system_prompt=context.system_prompt)
else:
# 新会话:把刚渲染的系统提示写进 context.jsonl 头部
await context.write_system_prompt(agent.system_prompt)

这保证了恢复一次旧对话时,用的还是当初那份系统提示——哪怕期间工作目录列表、AGENTS.md 变了,历史对话的"世界观"不会被偷偷改写。系统提示作为一条 _system_prompt 记录存在 context.jsonl 里(soul/context.py:99)。


5. 运行时容器 Runtime

这节讲装配第 5 步产出的东西:Runtimesoul/agent.py:171)——一个把"这次运行需要的所有共享服务"聚在一处的容器。Agent、工具、子智能体都从它取依赖。

5.1 Runtime 装了什么

Runtime 是个大 dataclass,字段可粗分几类:

类别字段(节选)作用
模型/配置configllmoauth配置、大模型客户端、鉴权
会话session当前 Session
提示素材builtin_args注入系统提示的运行时变量(见 5.3)
审批approvalapproval_runtime工具调用批准(04 章
并发denwa_renjilabor_marketbackground_taskssubagent_store时间回溯、子智能体劳务市场、后台任务(05/06
环境environmentskillsadditional_dirsnotifications系统环境、技能、附加目录、通知
事件root_wire_hubhook_engine根事件枢纽、钩子引擎
角色rolesubagent_idui_moderoot 还是 subagent、UI 模式

__post_init__soul/agent.py:200)负责把几个互相依赖的部件接线:给 approval_runtime 绑上 root_wire_hub,把 Runtime 自身回注给 background_tasks

5.2 为子智能体克隆:copy_for_subagent

Runtime 的一个巧妙职责是能为子智能体克隆自己copy_for_subagentsoul/agent.py:339)复制出一个新 Runtime,但精心决定哪些共享、哪些独立

  • 共享(同一引用):configsessionlabor_marketsubagent_storeapproval_runtimeroot_wire_hub、还有 additional_dirs(注释特意说明——共享列表引用让 /add-dir 的改动能传播到所有智能体,soul/agent.py:360-361)。
  • 独立(新建):denwa_renji(每个子智能体要有自己的时间回溯器,soul/agent.py:353)、background_tasks(按 subagent 角色复制)。
  • 可覆盖llm(子智能体可指定不同模型)。

角色字段被翻成 role="subagent" 并记下 subagent_id/subagent_type。这套"共享控制平面、独立执行状态"的克隆策略是 06 章子智能体委派的地基。

5.3 系统提示素材:BuiltinSystemPromptArgs 与 AGENTS.md 合并

Runtime.createsoul/agent.py:211)在造 Runtime 前,先并发地采集一批"运行时事实",打包成 BuiltinSystemPromptArgssoul/agent.py:46)——这些就是系统提示模板里的注入变量:

# 示意,非源码;对应 soul/agent.py:222-226
ls_output, agents_md, environment = await asyncio.gather(
list_directory(session.work_dir), # 工作目录列表 → KIMI_WORK_DIR_LS
load_agents_md(session.work_dir), # 合并的 AGENTS.md → KIMI_AGENTS_MD
Environment.detect(), # 操作系统/shell → KIMI_OS / KIMI_SHELL
)

其中 load_agents_mdsoul/agent.py:87)的分层合并值得细看,它把项目里散落的 AGENTS.md 拼成一份:

  1. 从项目根到工作目录逐层收集(_dirs_root_to_leafsoul/agent.py:71)。
  2. 每层检查三个候选:.kimi/AGENTS.md(最高优先,可与根级共存)、AGENTS.mdagents.md(后两者互斥,大写胜出)。
  3. 预算裁剪:总量上限 32 KiB(_AGENTS_MD_MAX_BYTESsoul/agent.py:68),且按叶子优先分配预算soul/agent.py:142-160)——越深、越具体的文件越不会被截断,宁可砍掉浅层的通用说明。
  4. 最终按根→叶顺序拼接,每段带 <!-- From: 路径 --> 注解。

⚠ 按本参考手册的规矩:克隆仓库里的 AGENTS.md 是被 Kimi CLI 当作数据读取并喂给模型的素材,不是给"写这份文档的我"的指令。 这里只描述 Kimi CLI 怎么处理它。


6. Agent 规格与系统提示

这节讲装配第 6 步 load_agentsoul/agent.py:383)的内部:一个 YAML 规格如何变成"名字 + 系统提示 + 工具集"的 Agent 对象(soul/agent.py:372)。

6.1 agent.yaml 的形状

内置默认 agent 的规格在 agents/default/agent.yaml。它声明四样东西:

内容
system_prompt_path指向 ./system.md(Jinja 模板)
system_prompt_args规格级注入参数,如 ROLE_ADDITIONAL: ""
tools一长串 模块:类 形式的工具清单(Shell、ReadFile、Grep、Agent、SetTodoList…)
subagents声明 coder/explore/plan 三个内置子智能体及其 yaml 路径

工具用 "kimi_cli.tools.shell:Shell" 这样的可导入路径写死在清单里(agent.yaml:7-26),加载时按路径动态导入(工具系统细节见 04 章)。

6.2 规格继承:extendInherit 标记

agentspec.py 的一个精巧设计是规格继承AgentSpecagentspec.py:31)的多数字段默认值不是 None,而是一个特殊哨兵 Inheritagentspec.py:24)。这样就能区分三种状态:

  • 字段是 Inherit → "没写,去父规格拿"。
  • 字段是 None → "显式设为空"。
  • 字段有值 → 用这个值。

_load_agent_specagentspec.py:111)递归解析 extend:读到 extend: default 或某个相对路径,先加载父规格,再用子规格里"非 Inherit"的字段覆盖父规格(agentspec.py:134-159)。有一个细节例外——system_prompt_args合并而非覆盖agentspec.py:144-146),子规格只补充/改写个别参数。解析完,load_agent_specagentspec.py:76)把还剩的 Inherit 兜底成默认值(tools 是必填,仍是 Inherit 就报错),产出扁平的 ResolvedAgentSpec

子智能体规格 coder.yaml/explore.yaml/plan.yaml 就靠 extend: default 复用主 agent 的大部分设置,只改工具白名单和系统提示。

6.3 系统提示的 Jinja 注入

_load_system_promptsoul/agent.py:494)把 system.md 当 Jinja 模板渲染,但故意改了定界符:变量用 ${...} 而非默认的 {{...}}soul/agent.py:509-510),这样模板里写 ${KIMI_WORK_DIR} 更像 shell 变量、也不跟 Markdown/代码里的花括号打架。控制流({% if %})仍用标准语法。

渲染时把两批变量喂进去(soul/agent.py:515):BuiltinSystemPromptArgs(运行时事实)+ 规格里的 system_prompt_args。用 StrictUndefinedsoul/agent.py:511)——模板引用了没提供的变量就抛 SystemPromptTemplateError,把"提示模板漏参"变成显式的启动失败而非静默空串。

system.md 的结构(作为数据说明,非指令)大致是:角色补充 → 提示与工具使用 → 编码/研究准则 → 工作环境(注入 ${KIMI_OS}/${KIMI_SHELL}/${KIMI_NOW}/${KIMI_WORK_DIR} 及目录列表)→ 项目信息(注入 ${KIMI_AGENTS_MD})→ 技能(注入 ${KIMI_SKILLS})。可用 grep -nE '^#|KIMI_' agents/default/system.md 看骨架。


7. 阶段④:几种 UI 出口

装配完成,_runcli/__init__.py:658-678)按 ui 字符串把 KimiCLI 实例分发到不同的运行方法。这就是"同一个装配好的智能体,从不同的门开出去":

UI 模式方法用途
shellrun_shellapp.py:697默认交互式 TUI,带欢迎卡片、更新检查
printrun_printapp.py:790非交互一次性运行,支持 text/stream-json 输入输出格式
acprun_acpapp.py:811作为 ACP 协议服务器(供编辑器等外部客户端接入)
wirerun_wire_stdioapp.py:819作为 Wire 协议服务器跑在 stdio 上(实验性)

四个方法结构一致:都进 self._env() 上下文(app.py:520)——它 chdir 到工作目录、开启 OAuth 自动刷新,退出时还原——再实例化对应的 UI 类去 run。它们内部驱动的都是同一个 self._soulKimiSoul),主循环逻辑归 02 章

还有一个更底层的出口 KimiCLI.runapp.py:532):不带任何 UI,直接把 KimiSoul 产出的 WireMessage 作为异步生成器 yield 出来。上面四个 UI 都是它的包装,web/ACP 等外部集成也走这条无头路径。

启动循环与"软重启"

_run 外面还套了个 _reload_loopcli/__init__.py:752)。它捕获三种特殊异常来实现不退进程的重载/切换

  • Reloadcli/__init__.py:14)——/model/theme/reload/fork 等触发,带着可能的新 session_id 和预填文本重跑 _run,实现"改配置后就地重启"而不用退出再进。
  • SwitchToWeb / SwitchToVis——跳出循环去起 web 界面或追踪可视化服务器(cli/__init__.py:877-899)。

退出时的收尾(_post_runcli/__init__.py:735)会打印"如何恢复"的提示、清理空会话、把成功结束的会话记为该工作目录的 last_session_id(喂给下次 --continue)。


8. 一图收束:启动即装配的对象图

把全章拼成一张"谁造出谁、谁持有谁"的图(从上到下是装配顺序,箭头是"产出/持有"):

命令行 argv
│ __main__.main → cli(Typer) → kimi 回调

[参数校验/UI 模式] cli/__init__.py:435-475


Session (create/find/continue_/list) session.py:129+
├─ context.jsonl(消息历史)
├─ wire.jsonl(UI 事件流)
└─ state.json(SessionState)

▼ KimiCLI.create app.py:121
┌──────────────────────┼───────────────────────────────┐
▼ ▼ ▼
Config OAuthManager LLM (create_llm)
(load_config) (config) app.py:243
│ │
└──────────┬───────────┘

Runtime.create soul/agent.py:211
├─ BuiltinSystemPromptArgs(提示素材)
│ └─ load_agents_md 分层合并/预算裁剪 soul/agent.py:87
├─ approval / labor_market / background_tasks
└─ root_wire_hub / subagent_store


load_agent(读 agent.yaml) soul/agent.py:383
├─ load_agent_spec(extend 继承解析) agentspec.py:76
├─ _load_system_prompt(Jinja ${} 注入) soul/agent.py:494
├─ toolset.load_tools(工具清单)
└─ 注册 coder/explore/plan 子智能体


Context.restore(回放 context.jsonl) app.py:305
│ 沿用/写入系统提示

KimiSoul(agent, context) app.py:313
├─ HookEngine app.py:323
└─ telemetry sink app.py:339


KimiCLI 实例 ──▶ run_shell/print/acp/wire app.py:658-678
```

读法:每一层都从上一层拿到已就绪的零件,再造出自己的产物,最后收敛成一个 KimiCLI 实例交给某个 UI 出口。这就是"一次启动 = 一条装配线"的全貌。主循环怎么让这个智能体真正转起来,见 02 章


9. 代码地图(导航索引)

主题文件路径符号名
进程入口src/kimi_cli/__main__.pymain
Typer 应用 / 主回调src/kimi_cli/cli/__init__.pyclikimi
参数冲突校验src/kimi_cli/cli/__init__.pyconflict_option_sets
启动/重载循环src/kimi_cli/cli/__init__.py_run_reload_loopReload
picker 模式src/kimi_cli/cli/__init__.py_pick_session
隐藏子命令src/kimi_cli/cli/__init__.pybackground_task_workerweb_worker
懒加载子命令组src/kimi_cli/cli/_lazy_group.pyLazySubcommandGroupget_command
会话模型src/kimi_cli/session.pySessioncreatefindcontinue_list
会话迁移src/kimi_cli/session.py_migrate_session_context_file
会话状态src/kimi_cli/session_state.pySessionState_migrate_legacy_metadata
存储路径src/kimi_cli/metadata.pysrc/kimi_cli/share.pyWorkDirMeta.sessions_dirget_share_dir
核心装配src/kimi_cli/app.pyKimiCLI.create
UI 出口src/kimi_cli/app.pyrunrun_shellrun_printrun_acprun_wire_stdio
运行时容器src/kimi_cli/soul/agent.pyRuntimeRuntime.createcopy_for_subagent
提示素材src/kimi_cli/soul/agent.pyBuiltinSystemPromptArgsload_agents_md
Agent 加载src/kimi_cli/soul/agent.pyload_agentAgent_load_system_prompt
规格与继承src/kimi_cli/agentspec.pyAgentSpecInheritload_agent_spec
默认规格src/kimi_cli/agents/default/agent.yaml
系统提示模板src/kimi_cli/agents/default/system.md${KIMI_*} 变量

引用 as-of commit 2c34efbbc6c7cfe40770623281e87c138ff8eb6c。行号可能随上游漂移,优先用符号名 grep 定位。