从零做一个自己的 CLI
从零做一个自己的 CLI引言装过 Claude Code 或 Codex CLI 的人都有同感终端里敲一行命令在哪个项目文件夹都能用不用点开浏览器也不用先找脚本在哪。这篇文章做两件事第一给已经能跑的Agent加一层CLI 外壳让它像上述工具一样随处可用第二讲清楚两种流式输出在实际开发里分别适合什么场景。文中的完整示例开源在 GitHubhttps://github.com/SWUSTcyt/travel-cli一个带工具调用与流式输出的 Agent CLI用旅游规划作演示场景。会一点 Python、有 API Key 就能跟着玩安装、环境变量与运行命令见仓库根目录README.md正文不展开pip install。文章目录从零做一个自己的 CLI引言一、CLI 速览是什么、为什么要做二、外层封装Typer 小例子 两层结构2.1 先建立直觉2.2 外壳长什么样三、Agent 核心注册工具、创建 Agent、Loop3.1 注册工具给 Agent 一双手3.2 Loop想一步、做一步、再想一步3.3 外壳怎么接到核心四、两种流式区别与开发中怎么选4.1 阶段流 --stream stage4.2 字段流 --stream instant4.3 怎么选一张表结语一、CLI 速览是什么、为什么要做CLICommand Line Interface命令行界面就是用键盘输入命令、在终端里拿结果。和 GUI点按钮的图形界面相对GUICLI操作鼠标点键盘敲命令例子网页 ChatGPTtravel run 杭州一日游一条命令通常长这样travel run帮我规划杭州一日游--streamstage │ │ │ │ 命令名 子命令 你的需求 可选参数为什么要做成 CLI两点就够随处可用——像 Claude Codepip install一次后任意目录都能敲不必cd到脚本文件夹。好分享、好复现——教程里写一行命令读者复制就能跑。如果只是自己试 Agent用python main.py或input()完全没问题要发 GitHub、写教程、给朋友用就需要再包一层 CLI。Agent 逻辑不用重写只是加外壳。示例项目travel-cli用「旅游规划」作演示但外壳封装、Loop、流式选型适用于任意 Agent 场景。二、外层封装Typer 小例子 两层结构2.1 先建立直觉你在终端敲travel run 杭州一日游 ↓ cli.pyTyper 外壳—— 解析命令和参数 ↓ runner.py loops/Agent 核心—— 搜网页、查地图、多轮推理重点Typer 和 Agently没有关系。Typer 只管「用户敲了什么」Agent 框架只管「怎么干活」。我们在现有 Agent 核心外面套了一层通用的 Python CLI 封装。[图两层结构示意——上方 Typer 外壳下方 Agent 核心]2.2 外壳长什么样摘自 travel-cli 的cli.py精简版importasyncioimporttyperfromtravel_cli.runnerimportrun_travel apptyper.Typer()app.command(run)defrun_cmd(request:str,stream:str|NoneNone,):asyncio.run(run_travel(request,streamstream))if__name____main__:app()逐行白话代码少但语法容易懵代码什么意思import typer引入第三方库 Typer专门用来写 CLIapp typer.Typer()创建一个 CLI「应用」对象app.command(run)装饰器把紧挨着的函数注册成子命令run你在终端敲travel run就会进这个函数request: str命令里杭州一日游这类文字会传进这个参数stream: str | None None可选参数不传就走默认批处理传stage/instant走流式asyncio.run(run_travel(...))Agent 内部是异步的async defTyper 函数是同步的用这一行把两者接上app()启动 CLI开始解析你在终端输入的内容再配一行pyproject.toml[project.scripts] travel travel_cli.cli:app执行pip install -e .后系统里就多了一个全局命令travel——和装 Claude Code 后在任意目录敲claude是同一类体验。对比没有外壳每次cd进项目目录再python xxx.py有外壳任意目录travel run ...三、Agent 核心注册工具、创建 Agent、Loop外壳只负责「接命令」。真正干活的在agent.py和loops/里。3.1 注册工具给 Agent 一双手摘自agent.pyfromagentlyimportAgentlyfromagently.builtins.actionsimportBrowse,Searchasyncdefbuild_travel_agent(workdir:str):agentAgently.create_agent()agent.set_agent_prompt(system,你是旅游辅助助手……)Search().register_actions(agent.action)Browse().register_actions(agent.action)awaitagent.async_use_mcp(fhttps://mcp.amap.com/mcp?key...)agent.action.register_bash_sandbox_action(allowed_workdir_roots[workdir],...)returnagent四步理解create_agent()—— 创建一个 Agent 实例。set_agent_prompt—— 设定角色与行为边界示例里是旅游助手可按业务替换。注册工具—— 搜索、读网页、高德地图 MCP、受控 bash相当于「能调用的能力」。use_actions在 runner 里调用—— 从注册表里激活要用的工具。3.2 Loop想一步、做一步、再想一步默认travel run走loops/batch.py。核心是Reason → Act → Reason → …循环flowTriggerFlow(nametravel_agent_loop)flow.chunkasyncdefreason(data):# 模型看用户需求和历史决定调工具还是给出最终回答decisionawaitresponse.async_get_data(...)print(f[Plan · Step{step}] …)# 终端里看到的 Planflow.chunkasyncdefact(data):# 按模型指定真正执行 search / browse / 地图 等resultawaitagent.action.async_execute_action(name,kwargs)print(f[Execute] …)# 终端里看到的 Execute终端里的[Plan]、[Execute]就是这样来的。默认模式下 Loop 全部跑完最后汇总[最终回答]——适合「我不着急只要结果」。3.3 外壳怎么接到核心runner.py里的run_travel()做编排agentawaitbuild_travel_agent(workdir)activate_travel_tools(agent)ifstreamisNone:resultawaitrun_batch_loop(agent,request)# 默认elifstreamstage:flowawaitbuild_stage_stream_flow(agent,request)resultawaitconsume_runtime_stream(execution,stage)else:flowawaitbuild_instant_stream_flow(agent,request)...项目结构壳 vs 核travel_cli/ ├── cli.py ← 外壳Typer 命令 ├── runner.py ← 编排选哪种跑法 ├── agent.py ← 核心工具注册 ├── loops/ ← 核心Loop 流式逻辑 └── display/ ← 核心流式事件打印到终端四、两种流式区别与开发中怎么选Agent 任务有时要跑一两分钟。干等像「卡死了」流式就是边跑边把进度推到终端类似 ChatGPT 逐字输出。travel-cli 提供两种流式对应两个命令行开关。4.1 阶段流--stream stage观察粒度一整步 Plan、一整步 Execute。# loops/stage_stream.py —— 每完成一步往流里推一条事件awaitdata.async_put_into_stream({phase:plan,# 或 executestep:step,reasoning:...,})# display/console.py —— 终端边读边打印asyncforrawinexecution.get_async_runtime_stream(...):print_stream_event(raw)终端示例[Plan · Step 1] tool: 先搜索杭州攻略… [Execute] search → … [Plan · Step 2] tool: 阅读网页…实际开发适合进度条、日志面板、运维监控——用户只需知道「现在在搜索 / 查地图」。4.2 字段流--stream instant观察粒度更细——模型结构化输出里哪个字段先写好就先推送。asyncforstreaming_datainresponse.get_async_generator(typeinstant):ifstreaming_data.event_typedone:awaitdata.async_put_into_stream({phase:plan_field,path:streaming_data.path,# 如 type、tool_namevalue_preview:str(streaming_data.value)[:100],})终端会多出行如↳ field 1.type tool ↳ field 1.tool_name search [Plan · Step 1] tool: …实际开发适合调试模型决策、精细 UI提前显示「即将调用 search」、可观测性要求高的场景。4.3 怎么选一张表默认travel run--stream stage--stream instant看到什么跑完后汇总每步 Plan / Execute每字段 每步复杂度最低中等较高典型场景脚本、CI、批处理终端进度、日志调试、精细 UI何时够用只要最终结果任务长、要「还在跑」要看模型字段级决策[图默认 run 与--stream stage终端输出对比截图]经验法则先默认跑通用户-facing 的 CLI 加stage排查模型行为或做高级 UI 再上instant。结语总结一下CLI 是外壳Agent 是核心——Typer 让你像 Claude Code 一样随处敲命令Agently 负责注册工具、跑 Loop。流式不是必选项默认模式够用就上默认要给用户「还在跑」的反馈用--stream stage要更细的可观测性用--stream instant。示例代码https://github.com/SWUSTcyt/travel-cli 欢迎 Star。留言区也可以说说你想给什么样的 Agent 加 CLI

相关新闻

运算放大器非理想特性解析:从直流精度到动态响应的工程实践

运算放大器非理想特性解析:从直流精度到动态响应的工程实践

1. 从“理想”到“现实”:运算放大器的两面性如果你问一个刚接触模拟电路的学生,运算放大器是什么,他大概率会告诉你:一个增益无穷大、输入阻抗无穷大、输出阻抗为零、带宽无穷大的“神器”。没错,这就是教科书上定义的…

2026/8/6 6:33:54 阅读更多 →
不止影音娱乐!智慧病房专用IPTV系统,解锁病房全新服务形态

不止影音娱乐!智慧病房专用IPTV系统,解锁病房全新服务形态

不止影音娱乐!智慧病房专用IPTV系统,解锁病房全新服务形态随着智慧医院建设持续升级,传统病房电视功能单一、适配性差的短板愈发凸显。区别于普通家用、商用IPTV,智慧病房专用IPTV系统深耕医疗专属场景,搭载多项独有核…

2026/8/6 6:33:54 阅读更多 →
城里教师竞争内卷,乡村教师有倾斜政策,很多人不知道怎么用好

城里教师竞争内卷,乡村教师有倾斜政策,很多人不知道怎么用好

每年职称评审季,我都能收到一堆老师的私信。有意思的是,这些私信分两类:一类是城里的老师,焦虑得整宿睡不着,反复问我哪个学校还有空岗;另一类是乡村的老师,政策明明给了一堆倾斜,却…

2026/8/6 6:33:54 阅读更多 →

最新新闻

基于RAG与LLM的视频内容理解:从原理到Python实战实现

基于RAG与LLM的视频内容理解:从原理到Python实战实现

最近在尝试各种AI工具时,发现很多开发者对Grok这个新兴的AI助手很感兴趣,特别是它处理视频内容的能力。网上关于“如何进入官网”、“如何安装”的讨论很多,但大多停留在基础操作,对于其核心功能——视频链接的总结与问答——缺乏…

2026/8/6 7:20:22 阅读更多 →
【 07A-步入交易生涯 | 阿布价格行为交易课程】

【 07A-步入交易生涯 | 阿布价格行为交易课程】

07A-步入交易生涯 | 阿布价格行为交易课程来源:B站 BV12ModBCERd | CID: 38383715113 | 时长约 35 分钟 转写工具:faster-whisper tiny 模型,已人工修正一、新手的错误观念 所有交易者在开始都会遇到一个问题——他们带着错误的信念进入市场。…

2026/8/6 7:20:22 阅读更多 →
AI文学创作抄袭检测算法解析与实现

AI文学创作抄袭检测算法解析与实现

1. AI文学创作中的抄袭检测算法解析最近两年AI写作工具呈现爆发式增长,从简单的文案生成到完整的小说创作,AI正在重塑内容生产流程。但随之而来的抄袭争议也愈演愈烈——当AI模型在海量文本数据上训练后,其输出内容与现有作品的相似度如何界定…

2026/8/6 7:20:22 阅读更多 →
MapGIS 6.7图形校准实战:JPG地图精准配准与坐标赋予

MapGIS 6.7图形校准实战:JPG地图精准配准与坐标赋予

1. 项目缘起:为什么一张JPG图片需要“校准”?如果你手头有一张从网上找到的、或者用手机随手拍下的JPG格式地图、规划图、地质剖面图,想把它导入到专业的GIS软件(比如MapGIS)里进行矢量化、分析或者叠加其他数据&#…

2026/8/6 7:19:21 阅读更多 →
Lua游戏AI开发:有限状态机(FSM)核心原理与实战应用

Lua游戏AI开发:有限状态机(FSM)核心原理与实战应用

1. 项目概述:为什么游戏AI需要有限状态机?在游戏开发,尤其是独立游戏或移动端游戏领域,Lua因其轻量、高效和易于嵌入的特性,成为了实现游戏逻辑和AI行为的热门选择。当你需要为一个NPC(非玩家角色&#xff…

2026/8/6 7:19:21 阅读更多 →
PyInstaller打包Python程序为EXE:从原理到实战的完整指南

PyInstaller打包Python程序为EXE:从原理到实战的完整指南

1. 项目概述:为什么需要打包Python代码? 如果你用Python写了个小工具,比如一个自动整理文件的脚本,或者一个数据分析的小程序,想分享给不会编程的同事或朋友用,最头疼的问题是什么?没错&#x…

2026/8/6 7:19:21 阅读更多 →

日新闻

深入解析LimboAI C++内核:架构设计与性能优化实战

深入解析LimboAI C++内核:架构设计与性能优化实战

1. 项目概述:为什么我们需要深入LimboAI的C内核?如果你是一名使用Godot引擎的游戏开发者,尤其是对AI行为逻辑有较高要求的项目,那么LimboAI这个名字你大概率不会陌生。它作为Godot 4生态中一个备受瞩目的行为树与状态机插件&#…

2026/8/6 0:00:06 阅读更多 →
Unity 2D游戏敌人AI系统:基于PlayMaker状态机与2D Toolkit的实战开发

Unity 2D游戏敌人AI系统:基于PlayMaker状态机与2D Toolkit的实战开发

1. 项目概述与核心思路大家好,我是老张,一个在游戏开发一线摸爬滚打了十多年的老码农。今天咱们接着聊《空洞骑士》风格2D动作游戏的Demo制作。上一期我们搭好了基础框架,处理了角色移动和碰撞,这一期,我们要让游戏世界…

2026/8/6 0:00:06 阅读更多 →
被动防火门市场前景发展趋势

被动防火门市场前景发展趋势

被动防火门依靠材质结构、密闭构造阻隔烟火蔓延,无需电控启动,是建筑被动消防系统核心构件,行业依托新规管控、城市更新、工业安全升级迎来稳定扩容,整体朝着合规化、专项化、低碳化、智能化方向发展。现阶段 GB12955‑2024 新版国…

2026/8/6 0:00:06 阅读更多 →

周新闻

最大流算法详解:从水管网络到Ford-Fulkerson与Dinic实战

最大流算法详解:从水管网络到Ford-Fulkerson与Dinic实战

1. 从水管网络到最大流:一个核心问题的诞生想象一下,你是一个城市供水系统的总工程师。你的城市有多个水源(水库),需要通过一个复杂的地下管道网络,将水输送到各个居民区。每条管道都有其最大通水能力&…

2026/8/5 15:00:43 阅读更多 →
基于Springboot的企业门户网站(源码+LW+调试文档+讲解)

基于Springboot的企业门户网站(源码+LW+调试文档+讲解)

温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台…

2026/8/5 13:13:56 阅读更多 →
MATLAB xcorr函数详解:从互相关原理到四大实战应用

MATLAB xcorr函数详解:从互相关原理到四大实战应用

1. 从一次信号“找茬”说起:为什么我们需要互相关几年前,我在处理一组声学传感器数据时遇到了一个棘手的问题。我有两个麦克风记录了一段相同的音频信号,理论上它们接收到的声音波形应该非常相似,只是由于麦克风位置不同&#xff…

2026/8/5 10:20:36 阅读更多 →

月新闻

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南 【免费下载链接】BaiduNetdiskPlugin-macOS For macOS.百度网盘 破解SVIP、下载速度限制~ 项目地址: https://gitcode.com/gh_mirrors/ba/BaiduNetdiskPlugin-macOS 还在为百度网盘macOS版的龟速下…

2026/8/5 23:28:39 阅读更多 →
终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 还在为网易云音乐下载的NCM格式文件无法在其他播放器播放而烦恼吗?ncmdump解密工具帮你轻松解决这个困…

2026/8/5 21:00:14 阅读更多 →
HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

AgentCard 智能体卡片:为英语学习 App 打造桌面级学习助手适用平台:HarmonyOS 7.0 (API 26 Beta)一、引言 HarmonyOS 7.0(API 26 Beta)新增了 AgentCard 智能体卡片能力,这是继 HMAF(鸿蒙智能体框架&#x…

2026/8/5 23:46:51 阅读更多 →