本文将完整复盘如何把 OpenCode 桌面版 打包成一个解压即用、纯离线、无需管理员权限的便携工具包,并集成自定义技能和常用插件。即便在加密且封闭的虚拟桌面环境下,它也能稳定工作。
一、方案目标
完全离线:所有依赖(Python 环境、Playwright 浏览器、npm 插件)都内置于文件夹中。
解压即用:用户只需解压 ZIP 并双击一个脚本,首次自动部署配置,后续直接使用。
无权限要求:不修改系统环境变量,不写入 Program Files,不强制管理员权限。
跨盘符自适应:无论解压到 C 盘、D 盘还是 R 盘,路径都能自动适配。
二、核心思路
便携 OpenCode 程序:将安装好的 OpenCode.exe(Windows)或 OpenCode.app(macOS)完整复制到工具包目录。
便携 Python 环境:使用 python -m venv --copies 创建完全独立的虚拟环境,确保拷贝到其他电脑也能正常运行。
自定义技能(Skills):用 Markdown 文件定义技能,配合 Python 脚本实现浏览器截图功能。
离线插件(Plugins):利用 Node.js 模块解析机制,通过“包装 JS 文件”桥接离线插件包,实现 PDF/Word 等高级文件解析。
启动引导脚本:负责首次部署技能文件、插件包装文件,并动态替换路径占位符,然后启动程序
三、详细搭建步骤
3.1 环境准备(构建机)
在一台可联网的电脑上完成以下操作:
安装 Node.js ——用于 npm 管理插件
安装 Python 3(3.8+)——用于创建虚拟环境和运行脚本
下载 OpenCode 桌面版安装包(Windows 选 .exe,macOS 选 .dmg)
3.2 构建目录骨架
新建一个根文件夹,例如 OpenCodePortable,内部结构如下:
OpenCodePortable/
├── @opencode-aidesktop/ # OpenCode 程序文件夹(Windows)
├── offline/
│ └── opencode_fies/
│ ├── python/ # 便携 Python 虚拟环境
│ ├── scripts/ # 自定义 Python 脚本
│ └── skills/ # 技能文件(.md)
├── plugin_wrappers/ # 插件包装文件(.js)
├── userdata/ # 用户数据目录
│ ├── opencode.jsonc # 插件配置文件
│ └── .config/opencode/
│ └── packages/ # 离线插件包
└── 启动.bat # Windows 启动脚本
3.3 制作便携 Python 环境
cmd
cd offline/opencode_fies python -m venv --copies python⚠️ 参数
--copies是核心,它会将python.exe和标准库拷贝到虚拟环境中,而不是创建链接,这样换到其他电脑才不依赖原系统。
激活环境并安装依赖:
cmd
python/Scripts/activate pip install playwright # 可选:pip install python-docx openpyxl PyPDF2 deactivate如果目标电脑已有 Chrome/Edge,我们就不必下载 Chromium;脚本中可指定channel="chrome"来调用系统浏览器。
3.4 编写功能脚本(以浏览器截图为例)
在scripts/下新建run_browser.py:
python
import sys, asyncio, datetime from playwright.async_api import async_playwright async def main(): print(f"[{datetime.datetime.now():%H:%M:%S}] Python 解释器: {sys.executable}") url = sys.argv[1] if len(sys.argv) > 1 else "https://www.baidu.com" output = sys.argv[2] if len(sys.argv) > 2 else "screenshot.png" print(f"[{datetime.datetime.now():%H:%M:%S}] 目标 URL: {url}") print(f"[{datetime.datetime.now():%H:%M:%S}] 截图保存: {output}") async with async_playwright() as p: print(f"[{datetime.datetime.now():%H:%M:%S}] 启动 Chrome...") browser = await p.chromium.launch(channel="chrome", headless=False) page = await browser.new_page() print(f"[{datetime.datetime.now():%H:%M:%S}] 正在加载页面...") await page.goto(url, wait_until="domcontentloaded") print(f"[{datetime.datetime.now():%H:%M:%S}] 页面加载完成,开始截图...") await page.screenshot(path=output, full_page=True) print(f"[{datetime.datetime.now():%H:%M:%S}] 截图完成!") await browser.close() print(f"[{datetime.datetime.now():%H:%M:%S}] 浏览器已关闭") asyncio.run(main())如果目标电脑只有 Edge,将
channel="chrome"改为"msedge"。
3.5 创建技能文件
技能文件存放在offline/opencode_fies/skills/<技能名>/SKILL.md,SKILL.md命名需完全一致
示例:浏览器截图技能browser-use-chrome
markdown
--- name: browser-use-chrome description: 打开网页并截图,使用系统 Chrome 浏览器 --- # 浏览器截图 ## 运行命令 `cmd /c "set PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1 && %OFFLINE_ROOT%\python\Scripts\python.exe %OFFLINE_ROOT%\scripts\run_browser.py {{url}} {{output}}"`注意:
Windows 命令使用cmd /c,macOS 应改为/bin/bash -c
环境变量%OFFLINE_ROOT%(或$OFFLINE_ROOT)会在启动脚本中设置,指向便携包内的offline/opencode_fies
{{url}}和{{output}}为参数占位符,由 OpenCode 自动填充
3.6 离线插件配置(PDF/Word)
很多高效插件(如opencode-betterread)底层依赖 npm 包和外部node_modules。离线加载的秘诀是:利用包装 JS 文件,让 Node.js 的模块解析机制自动找到依赖。
步骤 1:获取插件缓存
在联网的电脑上,先配置好opencode.jsonc并启动 OpenCode,插件会自动下载到缓存目录:
Windows:
%USERPROFILE%\.cache\opencode\packages\macOS:
~/.cache/opencode/packages/
将整个packages目录复制到便携包的userdata/.config/opencode/packages/下。
步骤 2:创建插件包装文件
在便携包根目录下创建plugin_wrappers文件夹,为每个插件新建一个.js文件,例如
opencode-betterread.js:
export * from '__PORTABLE_ROOT__/userdata/.config/opencode/packages/opencode-betterread/node_modules/opencode-betterread/dist/index.js';这里的__PORTABLE_ROOT__是占位符,启动脚本会在首次运行时替换为实际盘符路径。
步骤 3:修改opencode.jsonc
jsonc
{ "$schema": "https://opencode.ai/config.json", "plugin": [ "opencode-betterread", "opencode-parser", "opencode-multimodal" ] }插件实际代码留在packages中不动,包装文件会被部署到用户配置目录下,OpenCode 启动时自动识别。
7 编写启动脚本(Windows 示例)
在根目录创建启动.bat,内容如下:
@echo off setlocal enabledelayedexpansion :: 获取便携包根目录(去掉末尾反斜杠) set "PORTABLE_ROOT=%~dp0" if "%PORTABLE_ROOT:~-1%"=="\" set "PORTABLE_ROOT=%PORTABLE_ROOT:~0,-1%" :: 设置离线 Python 路径 set "OFFLINE_ROOT=%PORTABLE_ROOT%\offline\opencode_fies" :: ================================ :: 技能部署 :: ================================ set "SKILL_DEST=%USERPROFILE%\.config\opencode\skill\browser-use-chrome" if not exist "%SKILL_DEST%\SKILL.md" ( echo 正在初始化浏览器技能... mkdir "%SKILL_DEST%" 2>nul copy /y "%OFFLINE_ROOT%\skills\browser-use-chrome\SKILL.md" "%SKILL_DEST%\" ) :: ================================ :: 插件包装文件部署 :: ================================ set "WRAPPER_SRC=%PORTABLE_ROOT%\plugin_wrappers" set "PLUGINS_DEST=%USERPROFILE%\.config\opencode\plugins" if not exist "%PLUGINS_DEST%\opencode-betterread.js" ( echo 正在初始化插件... mkdir "%PLUGINS_DEST%" 2>nul copy /y "%WRAPPER_SRC%\*.js" "%PLUGINS_DEST%\" ) :: ================================ :: 替换占位符(如果包装文件使用了 __PORTABLE_ROOT__) :: ================================ set "WRAPPER_DEST_FILE=%PLUGINS_DEST%\opencode-betterread.js" if exist "%WRAPPER_DEST_FILE%" ( findstr /c:"__PORTABLE_ROOT__" "%WRAPPER_DEST_FILE%" >nul if %errorlevel% equ 0 ( powershell -Command "(Get-Content '%WRAPPER_DEST_FILE%') -replace '__PORTABLE_ROOT__', '%PORTABLE_ROOT:\=/%' | Set-Content '%WRAPPER_DEST_FILE%'" ) ) :: 如果 opencode.jsonc 中也有占位符,也进行替换 set "CONFIG_FILE=%PORTABLE_ROOT%\userdata\opencode.jsonc" if exist "%CONFIG_FILE%" ( findstr /c:"__PORTABLE_ROOT__" "%CONFIG_FILE%" >nul if %errorlevel% equ 0 ( powershell -Command "(Get-Content '%CONFIG_FILE%') -replace '__PORTABLE_ROOT__', '%PORTABLE_ROOT:\=/%' | Set-Content '%CONFIG_FILE%'" ) ) :: ================================ :: 启动 OpenCode :: ================================ start "" "%PORTABLE_ROOT%\@opencode-aidesktop\OpenCode.exe" --disable-gpu --disable-gpu-sandbox --disable-software-rasterizer --user-data-dir="%PORTABLE_ROOT%\userdata"四、用户使用流程
解压收到的 ZIP 包到任意盘符(路径不要有中文和空格)。
进入文件夹,双击
启动.bat。首次会看到黑窗提示“复制文件1”,稍等即自动打开 OpenCode。测试技能:
对话框输入用 browser-use-chrome 技能打开 https://www.baidu.com 并保存截图为 test.png测试插件:
对话输入“读取D:\报告\季度总结.pdf”,如果能提取文字说明插件生效。以后每次使用可以直接双击
OpenCode.exe(因为配置已写入系统),但推荐继续使用启动.bat以便后续更新
五、问题记录
1.opencode自动下载插件后,插件会位于C:\Users\Lenovo\.cache\opencode\packages
2.离线插件需要自己在.config中创建plugins文件夹并放置其中,位置位于C:\Users\Lenovo\.config\opencode下,由于插件包多为依赖外置的形式:包名/node_modules/包名(包依赖)/dist/index.js。因此需要建立js文件才能进行引入。该位置的插件被加载优先度会高于缓存中的插件
3.skill文件位于C:\Users\Lenovo\.config\opencode下,需自己创建skill文件夹,且要求文件名必须为SKILL.md,参考目录结构:skill文件夹/技能名称文件夹/SKILL.md
六、结语
通过这套方案,我们成功地在各种受限环境中搭建了一个功能齐全的离线 AI 工作台。从浏览器截图到 PDF 解析,从一键部署到跨机器迁移,整个流程无需任何联网或管理员权限,真正实现了“解压即用”。
教程仅提供思路,具体细节请结合实际情况变更。