加粗样式前面几篇我们把 AI 搭子从只会聊天养到了能自己学会发文章。可一直有个事梗在那儿这个搭子只活在我自己这台电脑上。换台机器就没了给别人也用不了。这不是一个人遇到的问题。你帮团队配好了一套 AI 工作流、攒了一整套规矩和工具——换个人来就从头再来一遍。不是每次都要重新教是那个装着搭子的环境搬不走。所以这一篇我想跟你聊的不是怎么搭一个 AI 搭子那前面几篇已经干完了是另一件事怎么把这个只属于你一个人的搭子封成一个标准化的、开箱即用的、换台机器还一模一样的——“罐头”。而封罐头这件事技术含量不在怎么封进去在另一件事上你划不划得清那条线——哪些是罐头厂焊死的、哪些是开罐人说了算的。这一刀是产品化设计的第一刀。一、能跑和能给别人用之间差着一刀我们团队之前有个 AI 助手内部跑得好好的。可要推到别的组去用每来一个新成员就要折腾一轮装 VS Code、装 OpenCode、配 Node.js 、拉插件、配工作目录、配规矩……光环境就折腾半天。而且 A 的配置和 B 的配置永远不完全一样——因为每个人都会按自己习惯调。你发现问题的根了吗我们一直在做同一件事把搭子出生的环境手动复刻到每台机器上。每复刻一次就多一次不一致的风险而且效率极低——从这个组推到那个组、从一个人推到一百个人人力成本是线性增长的。我停下来想了一件事这问题的解不是复刻环境而是把搭子装进一个罐头——开盖即用打开什么样、谁打开都一样。就像超市里的罐头你买回家打开里面的东西是一样的不会因为是你开的就不同。这个念头一转我发现自己问错了问题。不该问怎么把这个人的环境复制给那个人该问另一个问题。二、产品化设计的第一刀划清一条线所有把一个东西标准化给别人用本质都是一个设计问题哪些是我的地盘我管死哪些是用户的地盘我让出去。拿罐头来说——罐头里装什么、怎么装、保质期多久是罐头厂说了算的管死但什么时候开、怎么吃、配什么菜是开罐人说了算的让出去。生产标准归你使用方式归他。就这一刀。我的 AI 搭子要标准化就得先划这条线必须我自己焊死的编辑器本体、插件、OpenCode 运行时、默认呈现方式——这些变了搭子就不是那个搭子了。必须让用户掌控的工作区文件、用户配置、自定义规矩——这些都是用户自己的东西我替用户做主就是越界。灰色地带默认模板——用户没有这个文件时给一个最精简可用的但用户只要自己配了立刻让位。这个问题想清楚实现反而很薄。因为不需要从头造任何东西——已经有巨人站好了我只需要爬上去划那条线。三、三个开源巨人我只写一层胶水讲具体实现之前先说个你可能更关心的事实我没写一行编辑器代码没写一行 OpenCode 内核代码没写一行插件市场代码。我站在三个现成的东西上code-servercodercom 的开源项目——把 VS Code 网页版完好地封装成一个容器镜像。自带 entrypoint、dumb-init 进程管理、鉴权开关。我一行编辑器代码没写。OpenCodeopencode.ai 的开源项目——CLI 全局安装 VS Code 插件给这个工位配上真正的 AI 搭子运行时。我一行 Agent 内核没写。open-vsx 插件市场——社区维护的开源 VS Code 扩展市场离线下载插件 vsix 包。我一行商店代码没写。三个巨人我一个都没重新造。我做的事情只有一件写了一个 Dockerfile 把三个巨人装在一起 写了一个 entrypoint.sh 划那条线。这就是设计——设计不是从零到一写什么是从一到十怎么组合、怎么划界。我接下来把这层很薄的胶水掰碎了给你看。你可能不写 Docker、不做镜像但这套划界的设计思维能搬到任何产品化场景里。因为它不是在教你怎么封住一个东西是在教你怎么想清楚什么东西归平台、什么东西归用户。四、第一层秩序平台的地盘焊死谁都改不了先说我定的第一条规矩。这句话直接写进了代码扩展目录、用户数据目录、配置模板全部焊死在/opt。业务挂载工作目录或家目录也动不了它。为什么要这么较真容器化有个经典坑你默认把插件装在~/.vscode/extensions用户挂载了自己的家目录——插件没了。或者你把配置放在工作目录里用户挂载了另一个项目——全部乱套。我的解决方案特别笨把所有搭子运转必须的东西全部塞进一个目录/opt/code-server/然后用环境变量把业务请出这个区域EXTENSIONS_DIR/opt/code-server/extensions USER_DATA_DIR/opt/code-server/user-data TEMPLATE_DIR/opt/code-server/templates前两个很好理解扩展和数据。第三个可能你没想到——我把三份模板文件也固化在这里settings.json界面布局模板、tasks.json自动启动 OpenCode 的任务模板、AGENTS.md项目规矩模板、opencode.jsonOpenCode 配置模板。这意味着什么意味着不管用户怎么挂载他的工作目录、怎么替换家目录搭子的编辑器本体、插件、默认数据、配置模板一样都不会丢。这就是平台的地盘——你管不了、我焊死了谁来了都一样。但这不是全部。另一个更重要的原因我放在下一节说。五、第二层秩序seed-if-absent用户的事让用户做主你可以想一下如果镜像里把所有的配置都写死了——用户一启动全部用我的设置那他自己的配置放哪儿所以第二条规矩是默认注入但你只要自己带了我立刻让位。这句话落到代码里就是 entrypoint.sh 里反复出现的同一个模式seed_user_settings(){localuser_dir${USER_DATA_DIR}/Usermkdir-p${user_dir}if[!-f${user_dir}/settings.json];thenlogseeding default settings.json -${user_dir}cp${TEMPLATE_DIR}/settings.json${user_dir}/settings.jsonelselogsettings.json exists, keep business configfi}每一行都在说同一件事文件存在就不覆盖不存在才注入默认。工作目录的 AGENTS.md 是 seed-if-absent.opencode/opencode.json 是 seed-if-absent.vscode/tasks.json 也是。每一条都是你管我不管、你不管我兜底。这才是划地盘的另一半——你划清了什么归平台还要划清楚什么归用户。不是我塞给你的你都接着是我给你一个可用的默认但你只要自己配了你说的算。我见过太多产品化案例做反了的要么压死用户的配置空间满世界都是硬编码要么什么都不帮用户配开箱白屏。真正的设计在这两者之间——默认兜底 用户优先。这一层设计思想拿到任何给别人用的场景都通脚手架工具、配置管理器、CI/CD 模板库。核心就是同样的四个字seed-if-absent。你记住这四个字比记住我的 Dockerfile 值钱得多。六、第三层秩序exec 让位不越界前两层一个焊死地盘、一个让出用户空间第三层是给我自己定的规矩。entrypoint.sh 最后的启动是这样写的ARGS(...)exec/usr/bin/entrypoint.sh${ARGS[]}注意是exec——它把进程控制权交给 code-server 的官方 entrypoint而不是自己包一层、拦截信号、做额外处理。这意味着什么code-server 官方的 dumb-init、信号处理、存活检测全部原样透传。我不自作主张截断任何东西。这一层就一句话把自己当成一层很薄的胶水别把胶水当成平台。产品化设计里最容易犯的错就是你做了第一层封装觉得还不够再加一层再加一层——最后用户拿到的根本不是那个原汁原味的东西。但如果你能忍住在最薄的地方停下来——提供一个标准化的身体不碰用户怎么用这个身体、不碰鉴权、不碰编排——那你做的东西才是真正让别人用得放心的。七、开盖即用的呈现三个文件定的规矩好了地盘划完了。但用户最直观的感受不是地盘划得多清楚——他打开页面第一眼看到什么才是他判断这个好不好用的标准。这一篇我要做到一句话打开浏览器登录进去什么也不用点——OpenCode TUI 已经在主编辑区等着你了界面最精简、没有多余的侧边栏。为了做到这一句我只写了三个小文件code-server-settings.json20 行关掉欢迎页、关掉教程、关掉提示、关掉更新提醒、把终端放到主编辑区、把 CHAT 副边栏默认隐藏。tasks.json20 行声明一个folderOpen任务——工作区一打开自动在终端跑opencode命令。isBackground: true让它常驻后台presentation.focus: true让它一启动就把焦点给到 OpenCode TUI。AGENTS.md40 行这是 OpenCode 读取的规矩文件告诉 AI 助手它运行在什么环境里、能做什么、绝对不能做什么。三份文件加起来不到一百行就是全部开箱即用的工作量。你品品这个设计思路我没有写代码去调界面的那个瞬间而是写好模板让模板在启动时自动生效。模板驱动而不是代码驱动——这是开盖即用产品化的核心思路。因为模板是可替换的、可维护的、可复用的——业务想改呈现方式改模板就行不用改我那一堆胶水代码。八、写在最后回到最开始那件让我纠结的事一个人能用的 AI 搭子怎么变成谁都能有一个的标准件技术上的答案是封成一个镜像。但真正的答案是先想清楚那条线划在哪——哪些焊死归我、哪些让出去归用户、哪些默认兜底但不抢位。我站在三个开源巨人肩膀上只写了一层很薄的胶水一个 Dockerfile 一个 entrypoint.sh。设计真正的功夫不在你写了多少在你有没有想清楚什么不该写。往后你看任何产品化的工作——把一个工具打包给团队用、把一个配置模版化给新人用、把一个流程标准化给别人复刻——都可以用这一套划地盘的思维去拆平台焊死的边界在哪什么变了搭子就不是那个搭子了用户做主的边界在哪什么必须让用户自己说了算默认兜底的开关在哪什么情况下给默认、什么情况下让位这三刀想清楚你的罐头就封好了。这一篇我们封好了搭子的标准身体。可它现在还是被动的——没有人去叫它它不会自己醒来。下一篇我们给这个身体装一个大脑——一个能在你发出请求的瞬间自动调度一个属于你的搭子实例出来、用完再收回去的调度引擎。一百个人同时要 AI 搭子谁说了算咱们下篇见。关于 ArchAIHarness这篇文章是「看懂 AI 与智能体」专栏的一部分由ArchAIHarness持续输出。ArchAIHarness 是一套面向 AI 时代软件工程的人机协同架构哲学与公开工程资产主张架构师定义秩序AI 在秩序中生长。人立法AI 执行体系审计。如果你也希望 AI 在明确的架构边界内协作而不是在混沌中碰运气欢迎到 GitHub 上看看我们在做什么组织主页github.com/ArchAIHarness — 了解完整理念与资产全景本专栏zhuanlan-ai-and-agents— 所有文章的源码与发布记录实践指南docs— 架构哲学、工程方法和落地指南开源工具agent-workflows— 可复用的 AI 协作 Agents、Skills 与 Tools工程样例framework— DDD AI 协作的工程底座展示如何在开发中融合 AI本镜像build-on-vscode-opencode-image— 本文封装的标准身体把 VS Code 网页版 OpenCode 打成开箱即用的容器镜像Engineered by Architects · Empowered by AI · Audited by Discipline
我把 AI 搭子封成了罐头——没自己造一个零件,只划了一条线
发布时间:2026/7/10 23:21:19
加粗样式前面几篇我们把 AI 搭子从只会聊天养到了能自己学会发文章。可一直有个事梗在那儿这个搭子只活在我自己这台电脑上。换台机器就没了给别人也用不了。这不是一个人遇到的问题。你帮团队配好了一套 AI 工作流、攒了一整套规矩和工具——换个人来就从头再来一遍。不是每次都要重新教是那个装着搭子的环境搬不走。所以这一篇我想跟你聊的不是怎么搭一个 AI 搭子那前面几篇已经干完了是另一件事怎么把这个只属于你一个人的搭子封成一个标准化的、开箱即用的、换台机器还一模一样的——“罐头”。而封罐头这件事技术含量不在怎么封进去在另一件事上你划不划得清那条线——哪些是罐头厂焊死的、哪些是开罐人说了算的。这一刀是产品化设计的第一刀。一、能跑和能给别人用之间差着一刀我们团队之前有个 AI 助手内部跑得好好的。可要推到别的组去用每来一个新成员就要折腾一轮装 VS Code、装 OpenCode、配 Node.js 、拉插件、配工作目录、配规矩……光环境就折腾半天。而且 A 的配置和 B 的配置永远不完全一样——因为每个人都会按自己习惯调。你发现问题的根了吗我们一直在做同一件事把搭子出生的环境手动复刻到每台机器上。每复刻一次就多一次不一致的风险而且效率极低——从这个组推到那个组、从一个人推到一百个人人力成本是线性增长的。我停下来想了一件事这问题的解不是复刻环境而是把搭子装进一个罐头——开盖即用打开什么样、谁打开都一样。就像超市里的罐头你买回家打开里面的东西是一样的不会因为是你开的就不同。这个念头一转我发现自己问错了问题。不该问怎么把这个人的环境复制给那个人该问另一个问题。二、产品化设计的第一刀划清一条线所有把一个东西标准化给别人用本质都是一个设计问题哪些是我的地盘我管死哪些是用户的地盘我让出去。拿罐头来说——罐头里装什么、怎么装、保质期多久是罐头厂说了算的管死但什么时候开、怎么吃、配什么菜是开罐人说了算的让出去。生产标准归你使用方式归他。就这一刀。我的 AI 搭子要标准化就得先划这条线必须我自己焊死的编辑器本体、插件、OpenCode 运行时、默认呈现方式——这些变了搭子就不是那个搭子了。必须让用户掌控的工作区文件、用户配置、自定义规矩——这些都是用户自己的东西我替用户做主就是越界。灰色地带默认模板——用户没有这个文件时给一个最精简可用的但用户只要自己配了立刻让位。这个问题想清楚实现反而很薄。因为不需要从头造任何东西——已经有巨人站好了我只需要爬上去划那条线。三、三个开源巨人我只写一层胶水讲具体实现之前先说个你可能更关心的事实我没写一行编辑器代码没写一行 OpenCode 内核代码没写一行插件市场代码。我站在三个现成的东西上code-servercodercom 的开源项目——把 VS Code 网页版完好地封装成一个容器镜像。自带 entrypoint、dumb-init 进程管理、鉴权开关。我一行编辑器代码没写。OpenCodeopencode.ai 的开源项目——CLI 全局安装 VS Code 插件给这个工位配上真正的 AI 搭子运行时。我一行 Agent 内核没写。open-vsx 插件市场——社区维护的开源 VS Code 扩展市场离线下载插件 vsix 包。我一行商店代码没写。三个巨人我一个都没重新造。我做的事情只有一件写了一个 Dockerfile 把三个巨人装在一起 写了一个 entrypoint.sh 划那条线。这就是设计——设计不是从零到一写什么是从一到十怎么组合、怎么划界。我接下来把这层很薄的胶水掰碎了给你看。你可能不写 Docker、不做镜像但这套划界的设计思维能搬到任何产品化场景里。因为它不是在教你怎么封住一个东西是在教你怎么想清楚什么东西归平台、什么东西归用户。四、第一层秩序平台的地盘焊死谁都改不了先说我定的第一条规矩。这句话直接写进了代码扩展目录、用户数据目录、配置模板全部焊死在/opt。业务挂载工作目录或家目录也动不了它。为什么要这么较真容器化有个经典坑你默认把插件装在~/.vscode/extensions用户挂载了自己的家目录——插件没了。或者你把配置放在工作目录里用户挂载了另一个项目——全部乱套。我的解决方案特别笨把所有搭子运转必须的东西全部塞进一个目录/opt/code-server/然后用环境变量把业务请出这个区域EXTENSIONS_DIR/opt/code-server/extensions USER_DATA_DIR/opt/code-server/user-data TEMPLATE_DIR/opt/code-server/templates前两个很好理解扩展和数据。第三个可能你没想到——我把三份模板文件也固化在这里settings.json界面布局模板、tasks.json自动启动 OpenCode 的任务模板、AGENTS.md项目规矩模板、opencode.jsonOpenCode 配置模板。这意味着什么意味着不管用户怎么挂载他的工作目录、怎么替换家目录搭子的编辑器本体、插件、默认数据、配置模板一样都不会丢。这就是平台的地盘——你管不了、我焊死了谁来了都一样。但这不是全部。另一个更重要的原因我放在下一节说。五、第二层秩序seed-if-absent用户的事让用户做主你可以想一下如果镜像里把所有的配置都写死了——用户一启动全部用我的设置那他自己的配置放哪儿所以第二条规矩是默认注入但你只要自己带了我立刻让位。这句话落到代码里就是 entrypoint.sh 里反复出现的同一个模式seed_user_settings(){localuser_dir${USER_DATA_DIR}/Usermkdir-p${user_dir}if[!-f${user_dir}/settings.json];thenlogseeding default settings.json -${user_dir}cp${TEMPLATE_DIR}/settings.json${user_dir}/settings.jsonelselogsettings.json exists, keep business configfi}每一行都在说同一件事文件存在就不覆盖不存在才注入默认。工作目录的 AGENTS.md 是 seed-if-absent.opencode/opencode.json 是 seed-if-absent.vscode/tasks.json 也是。每一条都是你管我不管、你不管我兜底。这才是划地盘的另一半——你划清了什么归平台还要划清楚什么归用户。不是我塞给你的你都接着是我给你一个可用的默认但你只要自己配了你说的算。我见过太多产品化案例做反了的要么压死用户的配置空间满世界都是硬编码要么什么都不帮用户配开箱白屏。真正的设计在这两者之间——默认兜底 用户优先。这一层设计思想拿到任何给别人用的场景都通脚手架工具、配置管理器、CI/CD 模板库。核心就是同样的四个字seed-if-absent。你记住这四个字比记住我的 Dockerfile 值钱得多。六、第三层秩序exec 让位不越界前两层一个焊死地盘、一个让出用户空间第三层是给我自己定的规矩。entrypoint.sh 最后的启动是这样写的ARGS(...)exec/usr/bin/entrypoint.sh${ARGS[]}注意是exec——它把进程控制权交给 code-server 的官方 entrypoint而不是自己包一层、拦截信号、做额外处理。这意味着什么code-server 官方的 dumb-init、信号处理、存活检测全部原样透传。我不自作主张截断任何东西。这一层就一句话把自己当成一层很薄的胶水别把胶水当成平台。产品化设计里最容易犯的错就是你做了第一层封装觉得还不够再加一层再加一层——最后用户拿到的根本不是那个原汁原味的东西。但如果你能忍住在最薄的地方停下来——提供一个标准化的身体不碰用户怎么用这个身体、不碰鉴权、不碰编排——那你做的东西才是真正让别人用得放心的。七、开盖即用的呈现三个文件定的规矩好了地盘划完了。但用户最直观的感受不是地盘划得多清楚——他打开页面第一眼看到什么才是他判断这个好不好用的标准。这一篇我要做到一句话打开浏览器登录进去什么也不用点——OpenCode TUI 已经在主编辑区等着你了界面最精简、没有多余的侧边栏。为了做到这一句我只写了三个小文件code-server-settings.json20 行关掉欢迎页、关掉教程、关掉提示、关掉更新提醒、把终端放到主编辑区、把 CHAT 副边栏默认隐藏。tasks.json20 行声明一个folderOpen任务——工作区一打开自动在终端跑opencode命令。isBackground: true让它常驻后台presentation.focus: true让它一启动就把焦点给到 OpenCode TUI。AGENTS.md40 行这是 OpenCode 读取的规矩文件告诉 AI 助手它运行在什么环境里、能做什么、绝对不能做什么。三份文件加起来不到一百行就是全部开箱即用的工作量。你品品这个设计思路我没有写代码去调界面的那个瞬间而是写好模板让模板在启动时自动生效。模板驱动而不是代码驱动——这是开盖即用产品化的核心思路。因为模板是可替换的、可维护的、可复用的——业务想改呈现方式改模板就行不用改我那一堆胶水代码。八、写在最后回到最开始那件让我纠结的事一个人能用的 AI 搭子怎么变成谁都能有一个的标准件技术上的答案是封成一个镜像。但真正的答案是先想清楚那条线划在哪——哪些焊死归我、哪些让出去归用户、哪些默认兜底但不抢位。我站在三个开源巨人肩膀上只写了一层很薄的胶水一个 Dockerfile 一个 entrypoint.sh。设计真正的功夫不在你写了多少在你有没有想清楚什么不该写。往后你看任何产品化的工作——把一个工具打包给团队用、把一个配置模版化给新人用、把一个流程标准化给别人复刻——都可以用这一套划地盘的思维去拆平台焊死的边界在哪什么变了搭子就不是那个搭子了用户做主的边界在哪什么必须让用户自己说了算默认兜底的开关在哪什么情况下给默认、什么情况下让位这三刀想清楚你的罐头就封好了。这一篇我们封好了搭子的标准身体。可它现在还是被动的——没有人去叫它它不会自己醒来。下一篇我们给这个身体装一个大脑——一个能在你发出请求的瞬间自动调度一个属于你的搭子实例出来、用完再收回去的调度引擎。一百个人同时要 AI 搭子谁说了算咱们下篇见。关于 ArchAIHarness这篇文章是「看懂 AI 与智能体」专栏的一部分由ArchAIHarness持续输出。ArchAIHarness 是一套面向 AI 时代软件工程的人机协同架构哲学与公开工程资产主张架构师定义秩序AI 在秩序中生长。人立法AI 执行体系审计。如果你也希望 AI 在明确的架构边界内协作而不是在混沌中碰运气欢迎到 GitHub 上看看我们在做什么组织主页github.com/ArchAIHarness — 了解完整理念与资产全景本专栏zhuanlan-ai-and-agents— 所有文章的源码与发布记录实践指南docs— 架构哲学、工程方法和落地指南开源工具agent-workflows— 可复用的 AI 协作 Agents、Skills 与 Tools工程样例framework— DDD AI 协作的工程底座展示如何在开发中融合 AI本镜像build-on-vscode-opencode-image— 本文封装的标准身体把 VS Code 网页版 OpenCode 打成开箱即用的容器镜像Engineered by Architects · Empowered by AI · Audited by Discipline