Agentp: Turn OpenCode Into a Headless AI Engine for Your Editor, Terminal, and Telegram

Agentp: Turn OpenCode Into a Headless AI Engine for Your Editor, Terminal, and Telegram

I’ve always felt out of step with the prevailing trends. Before the AI explosion, the mantra was “ship fast” — the Minimum Viable Product. If you weren’t first, you were nobody. Quality, testing, documentation? Nice-to-haves. I could never stomach shipping “human slop” just to be first. 我一直觉得自己与主流趋势格格不入。在 AI 爆发之前,业界的口号是“快速发布”——即最小可行性产品(MVP)。如果你不是第一个做出来的,你就什么都不是。质量、测试、文档?这些都成了“可有可无”的东西。我始终无法接受为了抢先而发布“人类垃圾”代码。

Now we’re in the AI era, and suddenly everyone is alarmed about “AI slop.” And I find myself out of step again — because from where I stand, the AI helps me produce the opposite. Just as an example, I have a personal side project called SmarkForm and very little time to invest in it (but I keep pushing). Before AI it had a few “not-to-break-again” tests and a bare “just-the-docs” Jekyll site on GitHub Pages with often outdated code snippets and only a separate Examples section (which still exists) as the sole real demo. 现在我们处于 AI 时代,突然间每个人都对“AI 垃圾”感到恐慌。而我又一次感到格格不入——因为在我看来,AI 实际上是在帮我产出相反的结果。举个例子,我有一个名为 SmarkForm 的个人副项目,我投入的时间很少(但我一直在推进它)。在 AI 出现之前,它只有几个“防止再次崩溃”的测试,以及一个放在 GitHub Pages 上、仅有文档的 Jekyll 站点,其中的代码片段经常过时,唯一的真实演示就是一个单独的“示例”部分(现在依然存在)。

Nowadays almost every code snippet in the documentation is a working example of a SmarkForm-powered form whose source code can be edited in place. The test suite has been fully migrated to Playwright, covering up to 5 platforms and including a suite of co-located tests that ensure every example in the documentation keeps working. Moreover, the most recent inline examples are AI-authored (in Copilot’s words: “SmarkForm’s clean, declarative API makes it a natural fit for AI-assisted development”). 如今,文档中几乎每一个代码片段都是一个由 SmarkForm 驱动的、可原地编辑源代码的运行示例。测试套件已完全迁移到 Playwright,覆盖多达 5 个平台,并包含一套同位测试,确保文档中的每个示例都能持续运行。此外,最近的内联示例都是由 AI 编写的(用 Copilot 的话说:“SmarkForm 简洁的声明式 API 使其非常适合 AI 辅助开发”)。

The last “AI-free” bastion in the repository was the actual source code of the library, but nowadays I use AI there too — just with a more thorough review and a test-first approach. Put simply: my documentation is better. I write more tests than I could have imagined before. The code is cleaner. Even the worst AI-generated test is harmless: the most it can do is be useless. Unlike buggy production code rushed out to win a race, it won’t break anything — an occasional garbage-collection pass is all you need. 代码库中最后一个“无 AI”堡垒是库本身的源代码,但现在我也在那里使用 AI——只是采用了更彻底的审查和测试优先的方法。简单来说:我的文档质量更高了。我编写的测试比以前想象的要多得多。代码更整洁了。即使是最糟糕的 AI 生成的测试也是无害的:它顶多就是没用。与为了抢占先机而匆忙发布的带有 Bug 的生产代码不同,它不会破坏任何东西——偶尔进行一次垃圾清理就足够了。

The same goes for tooling. Every few years — sometimes months — a new IDE becomes the baseline, and if you haven’t switched you’re suddenly irrelevant. I use Neovim and tmux. Not because they’re trendy, but because I spent years evolving a workflow that works across physical terminals, remote servers, and whatever machine I happen to be sitting at. And, more importantly, it lets me focus on what I’m doing rather than how to do it. I’m not about to throw that away for a shinier editor. 工具方面也是如此。每隔几年——有时是几个月——就会有一个新的 IDE 成为基准,如果你没有切换,你就会显得过时。我使用 Neovim 和 tmux。不是因为它们时髦,而是因为我花了多年时间演进出一套工作流,它可以在物理终端、远程服务器以及我碰巧使用的任何机器上运行。更重要的是,它让我专注于“我在做什么”,而不是“如何去做”。我不会为了一个更花哨的编辑器而放弃这一切。

That’s the mindset behind the agentp trio. It started with just agentp, a simple CLI tool that pipes a prompt to an OpenCode server and returns the final answer while you see what’s going on in a spare monitor (when you have it). Then came ocmux, a project manager that manages a tmux session labeled as “Opencode” and keeps a dedicated OpenCode server and TUI for each project in a separate window. Finally, tgagentp is a Telegram bot that lets me talk to my projects (and even send and receive files) while away from the keyboard — and so much more. 这就是 agentp 三件套背后的设计理念。它最初只是 agentp,一个简单的 CLI 工具,将提示词(prompt)通过管道传输到 OpenCode 服务器并返回最终答案,同时你可以在备用显示器上看到处理过程(如果有的话)。接着是 ocmux,一个项目管理器,它管理一个标记为“Opencode”的 tmux 会话,并为每个项目在单独的窗口中保持一个专用的 OpenCode 服务器和 TUI。最后是 tgagentp,一个 Telegram 机器人,让我在离开键盘时也能与我的项目对话(甚至发送和接收文件)——以及更多功能。

Agentp grew from there — piece by piece, idea by idea — into a set of three zero-dependency Node.js CLI tools. It’s heavily AI-assisted, including the tests. I review every stage before shipping, but the real test is using it every day. Bugs happen; I value a working feature more than a flawless one. Agentp 就这样一点一滴、一个想法一个想法地成长起来,最终成为一套三个零依赖的 Node.js CLI 工具。它在很大程度上是 AI 辅助开发的,包括测试部分。我在发布前会审查每个阶段,但真正的考验是每天使用它。Bug 在所难免;比起完美无缺,我更看重功能是否可用。

In summary, now I can:

总结一下,现在我可以:

  • Pipe a prompt straight from Vim and replace my selection with the answer. 直接从 Vim 通过管道发送提示词,并用答案替换我的选区。
  • See what’s going on in an Opencode TUI that automatically switches to the right project. 在自动切换到正确项目的 Opencode TUI 中查看处理过程。
  • Get notified in Telegram when the answer is ready. 当答案准备好时在 Telegram 上收到通知。
  • Talk to the agent in charge of my project from Telegram while away from the keyboard. 在离开键盘时,通过 Telegram 与负责我项目的 Agent 对话。
  • Handle multiple projects and servers simultaneously from a Telegram group with topics. 通过带有主题(topics)的 Telegram 群组同时处理多个项目和服务器。
  • Queue messages while a server is busy and get threaded replies. 在服务器繁忙时排队消息,并获得线程化回复。
  • Leave private comments and public (for the agent awareness) notes in my telegram conversation. 在 Telegram 对话中留下私人评论和公开笔记(供 Agent 参考)。
  • Send files to the agent and ask the agent to send files to me through Telegram. 通过 Telegram 向 Agent 发送文件,并要求 Agent 向我发送文件。
  • Record a Telegram conversation and inject it as context into the next agentp response. 记录 Telegram 对话,并将其作为上下文注入到下一次 agentp 的响应中。
  • Threaded replies, permission request handling, and more… 线程化回复、权限请求处理等等……

The Three Tools

三大工具

agentp — The Pipe agentp — 管道

Stdin in, answer out. That’s the core loop. When you get used to writing text in Vim, all other text input methods feel clunky — and OpenCode TUI’s editor is no exception. Its /editor command lets you edit prompts in an external editor, but the whole TUI screen blanks out during the edit, which means a complete loss of context. 标准输入进入,答案输出。这就是核心循环。当你习惯了在 Vim 中编写文本,所有其他的文本输入方式都会显得笨拙——OpenCode TUI 的编辑器也不例外。它的 /editor 命令允许你在外部编辑器中编辑提示词,但在编辑过程中整个 TUI 屏幕会变空白,这意味着上下文的完全丢失。

My solution: I open the OpenCode TUI in a dedicated tmux session that I can maximize on a spare vertical monitor or just switch back and forth when working from a laptop. Then I write my prompts directly in Vim, visually select them, and send them to OpenCode by filtering them through agentp. I can either ask for a code snippet and get the answer in place, or use the —qa modifier to keep my prompt together with the answer. The latter lets me maintain a kind of logbook of prompts and answers so I can go back to review, copy chunks of code (or former prompts), etc. 我的解决方案是:我在一个专用的 tmux 会话中打开 OpenCode TUI,我可以将其在备用竖屏显示器上最大化,或者在用笔记本工作时来回切换。然后我直接在 Vim 中编写提示词,进行可视化选择,并通过 agentp 过滤发送给 OpenCode。我可以要求获取代码片段并原地获得答案,或者使用 --qa 修饰符将我的提示词与答案保留在一起。后者让我可以维护一份提示词和答案的日志,方便我回头查看、复制部分代码(或之前的提示词)等。

Basic usage: 基本用法:

printf "Summarize this file" | agentp
cat prompt.txt | agentp
# Target a specific session by name (partial match works)
cat prompt.txt | agentp --session "My Task"
cat prompt.txt | agentp --session "New Task" --new # create if not found
# Pull the last N answers without sending a new prompt
agentp --getLast 5
agentp --getLast 3 --qa # full QA pairs with rulers

Real magic from Vim/Neovim: 来自 Vim/Neovim 的真正魔法:

:'<,'>!agentp --qa

This replaces your visual selection with the answer. The optional —qa modifier preserves the prompt + answer with labels, so you keep the full context. 🚀 Spoiler: Passing the output of ocmux (without arguments) ensures the prompt goes to the right server and automatically switches the TUI in your spare monitor (or wherever) to the right project, instantly. 这会将你的选区替换为答案。可选的 --qa 修饰符会保留带有标签的提示词+答案,因此你可以保持完整的上下文。🚀 剧透:传递 ocmux 的输出(不带参数)可以确保提示词发送到正确的服务器,并自动将备用显示器(或任何地方)上的 TUI 瞬间切换到正确的项目。

:'<,'>!agentp --qa $(ocmux)

ocmux — The Project Manager ocmux — 项目管理器

Each project gets its own tmux window with a dedicated opencode serve + TUI pane. Auto-restarts dead panes, pins window names, stores state in .ocmux.json (discovered upward like .git). 每个项目都有自己的 tmux 窗口,配有专用的 opencode serve + TUI 面板。它会自动重启死掉的面板,固定窗口名称,并将状态存储在 .ocmux.json 中(像 .git 一样向上查找)。