https://elevenbeans.me - 一个纯静态的个人 profile 页面。有头像、有履历、有个暗色模式,平平无奇。
直到你按下 Ctrl+`。
终端来了。一个复古的绿色黑底 shell,带文件系统模拟 —— ls、cd、open,能浏览我的履历目录。谁还没个装逼的小心思呢对吧。
但故事没完。
如果你在终端里输入 codex、claude 或者 opencode,终端收起来,取而代之的是一个 AI 编程 Agent。
一个纯前端、零后端、零 LLM 依赖的 AI Agent 模拟器。长得像 OpenCode TUI,会显示 bash 命令执行、 read 文件、 edit 代码的 tool call 卡片,带打字机回复。
最搞笑的结果:你问 “open the pod bay doors”,它回 “I’m sorry, Dave. I’m afraid I can’t do that.” 然后跑一个 pod_bay_door --status 的 bash 卡片。
我一直觉得,好的个人网站应该有点彩蛋。不是那种”右键查看源代码”级别的隐藏文字,而是真的藏一个东西,让人意外一下。
去年 AI coding 爆发之后,天天在终端里跟 Agent 对话。那个界面本身就很有辨识度 —— 卡片式的 tool call、waiting animation、markdown 回复。我心想:这个交互形式本身就挺酷的,能不能复刻一个藏在个人主页里?
需求很简单:零依赖、纯前端、一个 HTML 搞定。
终端本身是一个早就有的功能。用一个 overlay div 模拟 CRT 显示器,font-family: monospace,绿色 #00ff41 文字,黑色背景,加上 @keyframes blink 的光标闪烁。
文件系统是个嵌套的 JavaScript 对象:
1 | |
ls、cd、open 命令遍历这个对象。简单、直白、不用任何库。
关键代码就几行。拦截 codex、claude、opencode 这三个命令,关掉终端 overlay,打开 Agent overlay:
1 | |
Agent 的核心是一个 agentResponses 数组。每个 entry 包含:
keywords:触发的关键词列表tools:预定义的 tool call 卡片(bash/edit/read)respond():返回回复文本的函数afterTools():可选,在 tool call 之后追加额外卡片输入 “hello”,它回一句问候。输入 “run tests”,它展示 5 个通过的测试用例。输入 “fix something”,它 read 一个文件然后 edit。输入 “deploy”,它执行 build、create PR、push 一条龙。
匹配逻辑是简单的 input.includes(keyword) 遍历。命中第一个就返回。没有命中任何关键词就走随机 fallback。
1 | |
没有 NLP、没有 embedding、没有 LLM。纯 includes。
每个 tool call 渲染一个带图标和内容的卡片:
1 | |
CSS 用了 GitHub Dark 配色的变体,#0d1117 背景,#c9d1d9 文字,tool call 卡片用 #21262d 背景加 #30363d 边框。
Agent header 有一个 class agent 用来区分用户和 agent 消息的颜色。但它恰好和 Agent overlay 的主容器 class 重名了。
CSS 里 .agent 容器设了 height: 85vh; max-height: 680px; border; overflow: hidden。
于是每个消息 header 都继承了 680px 高度和 overflow hidden。消息内容被裁掉了,看起来像坏了。
解法:把消息 header 的 class 从 .user/.agent 改成 .u/.a。
花了好久 (不得不人工介入将 model 从 Flash 切成了 Pro) 才定位到这个问题。
这个 Agent 完全是个玩具。它不会真的写代码,不会真的跑测试,所有的 tool call 输出都是预定义的。
但它反应了一个趋势:AI Agent 的交互范式正在变成一种新的 UI pattern。 Tool call 卡片、thinking animation、markdown 回复——这些正在成为用户熟悉的界面语言。
五年后回头看,也许”跟 AI 对话”会和”拖动鼠标”一样自然。
到时候这个彩蛋就是一个时代切片。
代码在 https://github.com/elevenbeans/myprofile - 试试在 elevenbeans.me 按下 Ctrl+Shift+`。