为什么 Memo Code 先做 CLI:以及终端输入框到底有多难搞

作者:mCell日期:2026/2/12

同步至个人站点:为什么 Memo Code 先做 CLI:以及终端输入框到底有多难搞

如果你对我的 Code Agent项目感兴趣,可以看这里:

Github Repo: Memo Code - Github

站点:Memo Web Site

大概四年前,我刚接触编程。学的是 C 语言,第一个程序当然是 hello world。

很简单,几行就写完。run 一下,弹出来一个 terminal(我已经忘了当时用的是什么:cmd?PowerShell?反正不重要),然后打印了一行:

“hello, world!”

从那以后,在我还没接触前端之前,我写的所有程序几乎都靠终端完成输入输出:猜数字、九九乘法表,再到后来刷算法,基本就是——写、跑、看终端、改、再跑。

那时候倒也没觉得有什么问题,只是偶尔会突然有点空虚: 难道以后我工作的成果,就是一直对着这个黑框框吗?

第一种认知:终端就是编程的全部

一开始我对“程序结果形态”的理解非常单一:

输入 → 运行 → 终端输出

终端就是一切:日志、交互、结果展示,全在那儿。 它很直接,很原始,也很“学生气”。

第二种认知:页面才是“程序结果”的另一种世界

后来我接触了前端。直到靠前端拿到第一份实习、第一份工作,我才对“程序结果形态”形成了第二种认知:

不仅仅是终端里几行日志,也可以是页面效果、动画、交互。 之后陆续做过小程序、App、桌面程序……那段时间里,终端更像“开发过程的工具”,而不是“产品本体”。

也就是从那时候开始,我对 terminal 的误解更深了: 它好像就应该是黑框框 + 命令 + 日志,仅此而已。

第三种认知:原来 terminal 也可以玩得这么花

25 年下半年,自从 Gemini CLI 这类东西开始出现之后,我对“程序结果形态”有了第三种认知:

原来 terminal 也可以玩得这么花。

彩色输出、输入框、选择框、进度条……该有的都有。 当时我没怎么深入研究,只是隐约意识到:以前我对 terminal 的理解偏了,它并不等于“只能打印”。

现实把我拉回来了:写 Agent,界面到底做什么?

后面开始做值班,又不得不把 Linux 命令捡起来:从 pwd / cat / tail / find,到 vi / vim……慢慢也熟练了。

直到最近两个月,我开始认真做我的 code agent:memogithub.com/minorcell/m…

等我写好了 MVP,写好了 runtime,写好了 toolrouter、tools 等;下一步突然被一个看起来很“产品”、但本质上很“工程”的问题卡住了:

**界面到底做什么?**传统 Web 页面?还是终端交互?

如果做传统 Web UI,我其实很拿手:加一个 HTTP server 包,再来个 Web UI 包就够了。 但现实是,市面上大多数 code agent(比如 claude code cli、codex cli)都是从终端交互做起的。后续再补 VSCode 插件、桌面版,甚至浏览器插件。

题外话:这里也不得不感慨一下——原来我大前端确实挺“六”的:只要界面能画出来,基本都能做。也更坚定一个想法:AI 时代,大前端技术只会更普及。

最终,可能是“理所当然”,也可能是对陌生技术栈的兴趣使然,我决定:memo code 的第一种产品形态,先做终端 CLI。

选 Ink:看起来都正常,直到输入框

调研开源的 Gemini CLI 时,我发现他们用的是 Ink(React for CLI)。我也就直接跟了:选 Ink。

一开始真的很顺:

  • 会话记录渲染没问题
  • slash 指令也能做
  • 封装组件库也舒服

似乎都挺好……直到我碰到最难的一块:输入框。

以前做 Web app:

天然、顺滑、毫无心理负担。

但在终端里,多行输入并不是默认就“应该支持”的体验。甚至 Ink 的 input 组件,也只有单行。

这时候你才会意识到:在终端里,“输入框”不是 UI 控件,它更像是一个小型编辑器。

我以为我解决了,结果只是解决了“最简单的部分”

我一开始尝试的方案很朴素,比如:

  • Shift + Enter 插入换行符

表面看起来能用了。 但很快更真实的问题出现了:粘贴文本。

粘贴一段文本时,你会遇到:

  • 显示残缺
  • 粘贴后光标位置不对
  • 输入状态偶尔乱跳

这时候我才明白:我不是在做“多行 input”,我是在终端里硬写一个“半个 textarea”。

如果对照二八法则:掌握 20% 的技术,就能做出 80% 的功能。

但要把剩下 20% 做好,往往需要补齐另外 80% 的细节。

终端交互就是这样:你很快能做出一个“能用”的 CLI;但要做得像样,细节多到离谱。

于是我最后认真设计了一套方案(写在这个 issue 里):github.com/minorcell/m…

解决方案:在 Ink 里做一个“可控的多行编辑器内核”

我最后没有继续纠结“有没有更好的 input 组件”,而是换了一个思路:

**把多行输入当成一个小型编辑器来做。**在 Ink 的限制里,把“编辑状态”和“渲染”解耦,然后在输入事件层做适配。

整个方案我拆成三个核心模块。

编辑器状态管理层

我不再把输入框当成“一个字符串”,而是当成一个状态机。

核心结构就是:

  • value: string(当前文本)
  • cursor: number(光标在文本中的位置)

听起来很简单,但一旦涉及多行、上下移动、终端折行,坑就开始密集出现:

  • 光标移动要能跨行
  • 上下键移动不能乱跳(要记住“我想待在哪一列”)
  • Unicode 也得小心:emoji / 代理对如果按字符串下标移动,光标很容易卡在“半个字符”上
  • 所以要做 clamp,保证 cursor 永远落在合法边界

这一层的目标只有一个:不管 Ink 怎么渲染,我内部都能稳定得到“当前文本是什么 + 光标在哪里”。

粘贴检测

真正让我没绷住的,其实是粘贴。

终端里粘贴一坨文本时,底层输入事件会被拆成很多个 keypress,然后 Ink / 渲染层每次都会触发更新。你会遇到一种非常诡异的现象:

你粘贴的是 A,但 UI 看起来像是 A 的碎片; 光标也像在“追不上输入”,最后漂到一个你完全无法理解的位置。

所以我做了一个“粘贴 burst 检测”:用启发式规则把粘贴从普通输入里识别出来,然后改成 缓冲 + 批量插入

  • 时间间隔规则(主机制):字符到达间隔 < 8ms 基本视为粘贴(人不可能这么快)
  • 字符数量规则(备用机制):连续字符 ≥ 16 时也按粘贴处理(对中文/emoji 路径更稳)
  • 识别到粘贴后进入状态机:pending → active → flush先塞 buffer,等“粘贴结束”再一次性写入 value,避免每个字符都触发一轮复杂计算

这一步做完之后,“粘贴残缺 / 光标乱跳”基本从玄学变成可控问题了。

输入处理适配器:快捷键 + 换行策略 + 视觉换行

终端输入要像编辑器,光靠“插入字符”是不够的,你还得补齐肌肉记忆:

  • 支持常见快捷键(Ctrl+A / Ctrl+E / Ctrl+U / Ctrl+K / Ctrl+W 这类)
  • 换行与提交要分开:
    • Shift + Enter 永远插入新行
    • Enter 默认提交
    • 但如果处在粘贴期间(或粘贴后的短窗口期),Enter 当作插入新行
      * 防止用户“粘贴完顺手一回车”直接把消息提交出去了(这个真的很常见)

还有一个关键点:逻辑行 vs 视觉行分离

  • 逻辑行:真正的 \n
  • 视觉行:终端宽度导致的自动折行

编辑用逻辑行,展示按视觉行计算,这样长段落在不同宽度终端也能保持一致体验。

同时,视觉换行还要能响应终端 resize(不然窗口一变宽/变窄,光标又漂移)。

这一层本质上就是:把终端输入从“能打字”推到“像个 textarea”。

念头通达,交给 codex 快速帮我实现了一个版本。

结果:我解决了剩下 20% 里最烦的 15%

这套方案不可能一把梭把所有边界问题抹平。 不同终端模拟器、不同输入法路径、极端大文本性能……仍然需要持续打磨。

但至少到这里,我觉得我把剩下 20% 里最难受、最影响体验的那 15% 解决掉了:

  • 多行输入稳定
  • 粘贴不再玄学
  • 光标不再乱飞
  • Enter / Shift+Enter 行为可控

收尾:终端不只是输入输出,它可以是简易版 Web App

memo 的这段实践,让我对终端交互有了更清晰的认知:

它不再只是我最开始学编程时那种“输入输出 + 打日志”。 它完全可以是简易版本的 Web App:有组件、有状态、有布局,甚至能长出一点“编辑器”的味道。

这感觉有点像当年最早的 HTML 刚出来时:朴素、克制,但足够表达。 而我现在做的,就是在这个黑框框里,把“能表达的东西”再往前推一点点。

如果你对我的 Code Agent项目感兴趣,可以看这里:

Github Repo: Memo Code - Github

站点:Memo Web Site


为什么 Memo Code 先做 CLI:以及终端输入框到底有多难搞》 是转载文章,点击查看原文


相关推荐


Java8 API文档搜索引擎_优化构建索引速度
_周游2026/2/3

本专栏前文已介绍完成索引模块程序: https://blog.csdn.net/m0_63299495/article/details/157515700?spm=1011.2415.3001.5331https://blog.csdn.net/m0_63299495/article/details/157515700?spm=1011.2415.3001.5331并对关键部分进行了细节整理: https://blog.csdn.net/m0_63299495/article/details


Linux软件安装 —— Flink集群安装(集成Zookeeper、Hadoop高可用)
吱唔猪~2026/1/25

文章目录 一、节点说明二、配置节点间免密登录三、JDK安装四、Zookeeper安装五、Hadoop安装六、Flink安装1、基础环境准备(1)下载安装包(2)上传并解压 2、修改配置(1)配置zookeeper(2)配置flink-conf.yaml(3)配置workers(4)创建必要的目录(5)配置环境变量 3、分发flink 七、集群测试1、启动zookeeper,hadoop2、Yarn Session测试(1)模式介绍(2)准备测试资源


图解DeepSeek最新论文,人人都能看得懂!
饼干哥哥2026/1/16

DeepSeek 又发论文了。 这一次,没有惊天动地的参数军备竞赛,没有万卡集群的暴力美学。 他们只是冷静地指出了当前 AI 届一个“皇帝的新衣”: 我们最顶尖的大模型,其实都在做着极其愚蠢的事情。 在这篇名为《Conditional Memory via Scalable Lookup》(基于可扩展查找的条件记忆)的论文中,DeepSeek 创始人梁文锋亲自署名,揭示了下一代大模型架构(V4?)的核心秘密:与其让模型更努力地“思考”,不如教它学会“作弊”。 01.愚蠢的天才:为什么要用算力去


如何在CentOS 7.9 服务器上配置并优化 Ceph 分布式存储集群,提升数据冗余与性能?
A5IDCCOM2026/1/8

本文基于A5IDC在真实生产环境(跨机房 Ceph 集群支撑虚拟机盘、对象存储及容灾复制)的实战经验,详细讲解如何从零部署 Ceph 集群在 CentOS 7.9 上,并通过硬件配置选择、网络优化、Ceph 参数调优等实用细节提升 数据冗余能力与性能表现。文章包含具体产品型号、系统配置表、命令示例与性能评估对比表,适合中大型数据中心储存架构实施。 一、背景与目标 随着业务系统对海量数据持久层的要求不断提升,我们需要一个高可靠、易扩展、具有自动自愈能力的分布式存储平台。Ceph 是开源生态


Git/Gitee/GitHub有什么区别
lifewange2025/12/31

Git、GitHub、Gitee(码云)三者核心区别 & 完整详解 你想弄清楚这三者的关系和差异,本质上Git 是「工具」,GitHub/Gitee 是「平台」,这是最核心的定位区别,三者不是同一维度的东西,先把这个核心逻辑吃透,所有差异就一目了然了。 ✅ 一、三者的「本质定位」(最核心,必记) 1. Git —— 本地的「版本控制系统」(纯软件 / 工具) Git 是一个免费、开源的分布式版本控制软件,它是一个安装在你电脑本地的程序 / 工具,不依赖任何网络、不依赖任何网站就能独立运行


Apache Tika XXE注入漏洞 | CVE-2025-66516 复现&研究
探索宇宙真理.2025/12/21

0x0 背景介绍 Tika Pdf Parser Module是Apache软件基金会开发的Java库,专用于解析PDF文件内容。核心功能包括文本提取、元数据解析及嵌入式对象处理,基于Apache Tika框架实现,依赖PDFBox等开源库。 Apache Tika的tika-core(1.13-3.2.1)、tika-pdf-module(2.0.0-3.2.1)和tika-parsers(1.13-1.28.5)模块存在严重XXE漏洞(跨平台),攻击者可通过构造PDF内的XFA文件实施XM


tig 的untracked changes和unstaged changes含义?
aoxiang_ywj2025/12/13

背景:你理解tig中untracked changes和unstaged changes的含义?它们对应的代码存在哪里呢?在本地仓库?提交到gitlab线上库了?下面将解答这些疑问。 一、核心结论先明确 tig 中显示的 Untracked changes(未跟踪变更)和 Unstaged changes(未暂存变更)都属于本地工作区的修改,完全没有提交到 GitLab 线上库,甚至连「本地仓库的提交(commit)」都没完成 —— 它们和 GitLab 线上库没有任何关联,仅存在于你的本地


iOS内存映射技术:mmap如何用有限内存操控无限数据
sweet丶2025/12/5

当一个iOS应用需要处理比物理内存大10倍的文件时,传统方法束手无策,而mmap却能让它流畅运行。这种神奇能力背后,是虚拟内存与物理内存的精密舞蹈。 01 内存管理的双重世界:虚拟与物理的分离 每个iOS应用都生活在双重内存现实中。当你声明一个变量或读取文件时,你操作的是虚拟内存地址,这是iOS为每个应用精心编织的“平行宇宙”。 这个宇宙大小固定——在64位iOS设备上高达128TB的虚拟地址空间,远超任何物理内存容量。 虚拟内存的精妙之处在于:它只是一个巨大的、连续的地址范围清单,不直接对应


花 200 美刀买“黑盒”?Claude Code 这波更新,把程序员当傻子了吧…
Dcs2026/2/21

有些产品吧,功能再强,只要开始“藏事儿”,程序员的雷达立马就响了: 你到底读了哪个文件?你到底搜了啥?你到底改了啥?——别跟我说“别管细节,反正我很聪明”。哥们,工程不是玄学,是可验证、可追溯、可复盘。 然后,Claude Code 2.1.20 就真把这事做了:把“读取文件路径”和“搜索 pattern”这种最基础的可观测信息,直接干没了。 1)更新前 vs 更新后:从“可审计”变成“随缘”🤡 以前你会看到它读了哪些文件、搜了什么关键词,属于那种一眼就能判断它有没有跑偏的“低噪音透明输出”


在OrangePi-5 Plus/5 Ultra上实时运行yolo26进行无人机检测,fps超50!
吃素的力2026/3/1

在OrangePi-5 Plus/5 Ultra上使用VideoPipe与YOLO26n实现高性能无人机检测 视频效果展示 RK3588无人机检测 前言 随着低空经济的快速发展,无人机检测已成为安防监控、边境巡逻、关键区域保护等场景中的重要需求。OrangePi 5 Plus和OrangePi 5 Ultra作为瑞芯微RK3588平台的高性能开发板,凭借其强大的NPU算力,成为边缘端AI推理的理想选择。 本文将详细介绍如何基于VideoPipe框架,结合最新的Y

首页编辑器站点地图

本站内容在 CC BY-SA 4.0 协议下发布

Copyright © 2026 XYZ博客