1. 为什么 bash 工具提示词总在重启后失效如果你正在用 OpenCode 这类 Agent 框架跑自动化任务大概率遇到过这种场景第一次会话里你精心调教好了 bash 工具的行为规则——比如强制所有命令在项目根目录执行、禁止用cd xxx command这种写法、文件读写必须走专用文件工具——结果关掉会话重新打开AI 又变回默认状态该用cd还是用cd该乱跑目录还是乱跑。这不是 OpenCode 的 bug而是提示词加载机制决定的。OpenCode 的 bash 工具提示词默认走的是「会话级注入」每次新建会话时框架从内置模板或临时上下文里拼一份提示词塞给模型会话结束这份拼装结果就丢了。你手动改的那份只存在于当前进程的内存里没有落到磁盘上的配置文件自然谈不上跨会话生效。真正要解决的是「持久化」这件事。持久化分两层一层是 Shell 进程的会话保持常驻后台进程让cd、export在连续命令间连贯另一层是提示词本身的持久化——把工具行为规则写进settings.json让 OpenCode 每次启动都从同一个地方读取而不是每次重新拼。前者是运行时机制后者是配置机制两者配合才能让 bash 工具的行为稳定下来。这篇聚焦第二层。我会给出一个可直接复制的settings.json骨架把 bash 工具提示词、TaoToken 统一 Key/API 通道接入点一起配好然后带你走一遍「改配置 → 重启会话 → 验证提示词是否真的持久生效」的完整流程。适合需要让工具提示词跨会话稳定生效的开发者尤其是已经在用 OpenCode 跑 Agent 任务、被重复调试折磨过的人。2. TaoToken 前置统一 Key 与 API 通道接入点在写settings.json之前先把模型接入这一层理清楚。OpenCode 的 bash 工具提示词要生效前提是模型请求能正常打到后端而请求走哪条通道、用哪个 Key直接决定了配置里provider段怎么写。TaoToken 在这里的角色是统一接入层你不需要为每个模型单独维护一套 Key 和 endpoint而是用同一个 API 通道把 Claude、GPT 等模型的请求统一转发出去。对 OpenCode 来说这意味着settings.json里的 provider 配置可以收敛成一份bash 工具提示词也只需要挂在这一份配置下不用按模型分叉。具体要准备两样东西第一是 API Key。到控制台生成一个注意它是敏感凭证别写进会提交到 Git 的文件里建议用环境变量注入。生成入口在控制台的 API Keys 页面地址是https://taotoken.net/console/api-keys?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewrite。第二是 API 通道地址。TaoToken 的 API 基址是https://taotoken.net/api注意这个地址不带 UTM 参数直接作为baseURL写进配置即可。如果你用的是 Anthropic 兼容协议OpenCode 默认走这套endpoint 拼接规则是baseURL /v1/messages这个后面在配置里会体现。提示Key 建议放在环境变量TAOTOKEN_API_KEY里settings.json中通过${TAOTOKEN_API_KEY}引用。这样配置文件可以安全地进版本库Key 不会泄露。如果你还没决定用哪个模型跑 Agent 任务可以先去模型对话页面试一下不同模型在 bash 工具调用上的表现地址是https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewrite。长期跑编码和 Agent 任务的话Coding Plan 会更划算入口在https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewrite。3. settings.json 配置骨架把 bash 提示词钉死在磁盘上OpenCode 的配置文件默认放在项目根目录的.opencode/settings.json也可以放在用户级目录~/.config/opencode/settings.json。项目级配置优先级更高适合把 bash 工具提示词和项目绑定用户级配置适合全局统一行为。下面这份骨架以项目级为例你可以直接复制后改路径和 Key 引用。{ provider: { taotoken: { type: anthropic, baseURL: https://taotoken.net/api, apiKey: ${TAOTOKEN_API_KEY}, models: { claude-sonnet: { id: claude-sonnet-4-20250514, maxTokens: 8192 } } } }, defaultModel: taotoken/claude-sonnet, tools: { bash: { enabled: true, persistPrompt: true, promptFile: .opencode/prompts/bash.md, prompt: 你是一个终端命令执行工具。所有命令默认在当前项目根目录下运行。如果需要切换到其他目录必须使用 workdir 选项指定路径禁止使用 cd xxx command 的写法。本工具仅用于执行终端操作禁止用它读写、编辑或查找文件内容文件的增删查改必须使用专用文件工具。命令执行需保持会话连贯环境变量和当前目录状态在连续命令间应保持一致。, timeoutMs: 120000, session: { persistent: true, snapshotOnExit: true, snapshotPath: .opencode/state/bash-snapshot.json } } }, session: { restoreOnStart: true } }几个关键字段说明一下。persistPrompt设为true是持久化的开关它告诉 OpenCode 不要每次会话重新拼提示词而是从promptFile指定的文件读取。promptFile指向.opencode/prompts/bash.md你可以把完整的 bash 工具提示词写在这个 Markdown 文件里比塞在 JSON 字符串里好维护得多。prompt字段是兜底当promptFile不存在时用它。session.persistent和snapshotOnExit对应前面说的两层持久化前者让 Shell 进程在会话期间常驻后者在进程退出前把目录状态和环境变量快照写到snapshotPath。session.restoreOnStart设为true下次启动时自动读快照恢复。如果你想把提示词单独维护创建.opencode/prompts/bash.md内容就是你要固化的规则# bash 工具行为规则 1. 所有命令默认在当前项目根目录下运行。 2. 需要切换目录时使用 workdir 选项指定路径禁止 cd xxx command。 3. 本工具仅执行终端操作禁止读写、编辑、查找文件内容。 4. 文件增删查改必须使用专用文件工具。 5. 连续命令间保持会话连贯环境变量与当前目录状态需一致。 6. 命令超时上限 120 秒超时后进程由守护机制清理。这样配置的好处是提示词和配置分离改规则只动 Markdown不用碰 JSONpersistPrompt保证每次启动都从磁盘读不会因为会话重建而丢失。4. 验证请求重启会话后提示词是否真的生效配置写完不代表生效必须验证。验证分三步先确认配置被正确加载再确认提示词被注入最后确认跨会话持久。第一步检查配置加载。在项目根目录执行opencode config show --tool bash如果配置正确输出里应该能看到persistPrompt: true、promptFile: .opencode/prompts/bash.md以及session.persistent: true。如果这几项是false或缺失说明配置文件路径不对或者 JSON 语法有误。JSON 不允许尾随逗号这是最常见的坑。第二步验证提示词注入。启动一个会话让 Agent 执行一个需要切目录的命令观察它的行为opencode run 列出 src 目录下的所有文件如果提示词生效Agent 不会输出cd src ls而是会调用 bash 工具并带上workdir: src参数。你可以在会话日志里看到工具调用的入参确认workdir字段存在。如果它还是用cd说明提示词没被读到回去检查promptFile路径是不是相对于项目根目录。第三步验证跨会话持久。这一步是关键。先在一个会话里设置一个环境变量opencode run export MY_TEST_VARhello_persist echo done然后完全退出 OpenCode重新启动一个新会话执行opencode run echo \$MY_TEST_VAR如果输出hello_persist说明快照恢复生效环境变量跨会话持久了。如果输出为空检查snapshotPath指向的文件是否存在以及restoreOnStart是否为true。同样的方法验证提示词持久重启后让 Agent 再执行一次切目录命令如果它依然用workdir而不是cd说明提示词从磁盘读取成功持久化配置到位。注意验证环境变量持久时export和echo必须在同一个 Shell 会话的上下文里。如果你分两次opencode run调用中间进程退出了那验证的其实是快照恢复而不是会话保持两者要区分开。5. 本篇常见错排查配置过程中最容易踩的坑集中在几个地方我按出现频率排一下。配置不生效config show里字段还是默认值。九成是文件位置问题。OpenCode 读配置的顺序是项目级.opencode/settings.json 用户级~/.config/opencode/settings.json 内置默认。如果你把配置写在了项目根目录的settings.json没有.opencode目录它不会被读到。确认路径是.opencode/settings.json。提示词文件读不到Agent 行为没变化。检查promptFile的路径基准。它是相对于项目根目录解析的不是相对于配置文件所在目录。如果你写的是prompts/bash.md而文件实际在.opencode/prompts/bash.md就会读不到。另外确认文件编码是 UTF-8中文提示词用其他编码会乱码。环境变量引用失败报 Key 无效。settings.json里的${TAOTOKEN_API_KEY}是运行时展开的前提是这个环境变量在当前 Shell 里存在。如果你在.zshrc里 export 了但用的是 bash或者反过来就会读不到。用echo $TAOTOKEN_API_KEY确认当前 Shell 能打印出值。另外注意别在 Key 前后带空格或引号。快照恢复后目录状态不对。snapshotPath指向的文件如果被手动删了或者项目被移动了位置快照里的绝对路径就失效了。建议快照文件放在项目内如.opencode/state/并且把.opencode/state/加进.gitignore避免快照进版本库造成冲突。超时后进程没清理干净。timeoutMs设得太长比如 600000会导致异常命令挂很久。建议 120000 起步配合snapshotOnExit做兜底。如果发现后台有残留的 Shell 进程检查session.persistent是否和snapshotOnExit同时开启只开前者不开后者进程退出时状态会丢。改了配置但没重启会话。OpenCode 的配置在会话启动时加载一次运行中改settings.json不会热更新。改完必须完全退出再启动opencode run每次是新进程所以没问题但如果你用的是常驻的 TUI 模式要手动重启。6. 接入与排障把配置一次做对配置这件事做对一次比反复调试省事得多。核心就三点Key 走环境变量、提示词走独立文件、持久化开关显式打开。settings.json骨架里的persistPrompt、promptFile、session.persistent、snapshotOnExit、restoreOnStart这五个字段是持久化的关键缺一个都可能导致跨会话失效。如果你在接入过程中遇到 Key 或通道问题先去 API Keys 页面确认 Key 状态地址是https://taotoken.net/console/api-keys?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewrite。配置字段的具体含义和更多示例接入文档里有完整说明入口在https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewrite。如果你用的是 Claude Code 或 Anthropic 协议相关的工具链Anthropic 接入页有对应的配置对照地址是https://taotoken.net/claudecode-anthropic?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewrite。验证环节别偷懒。opencode config show --tool bash确认加载workdir参数确认提示词注入重启后echo $VAR确认快照恢复。这三步走完bash 工具提示词的持久化就算真正落地了。后面再调规则只改.opencode/prompts/bash.md重启会话即可不用再动 JSON 骨架。