oh-my-pi bash 工具深度解析:输入参数、审批策略、拦截路由与 PTY/后台作业执行路径
2026/9/10 0:54:14 网站建设 项目流程

oh-my-pi bash 工具深度解析:输入参数、审批策略、拦截路由与 PTY/后台作业执行路径

【免费下载链接】oh-my-pi⌥ Coding agent with the IDE wired in项目地址: https://gitcode.com/GitHub_Trending/oh/oh-my-pi

在 oh-my-pi(一个把 IDE 能力接入的编码 Agent)中,bash工具是模型执行 shell 命令的统一入口:它负责命令校验、审批策略判定、专用工具拦截路由、内部 URL 展开、PTY/前台/后台/客户端终端四种执行路径的分发,以及输出截断与 artifact 溢出。读完本篇,你将掌握bash工具全部输入参数的语义与默认值、bash.patternsbashInterceptor.patterns两套独立策略的配置方式与交互规则,以及从BashTool.execute()到原生 Shell/PtySession 的完整执行管线,从而能够精确配置审批与路由规则并排查执行异常。

一、bash 工具的定位与源码布局

oh-my-pi 中存在两个 bash 执行面:

  1. 工具调用面toolName: "bash"):模型调用 bash 工具时使用,入口是 BashTool.execute(),参数包括command、可选的envtimeoutcwdpty,以及当async.enabled为 true 时的async
  2. 用户 bang 命令面(交互式输入或 RPC 中的!cmd):会话级辅助路径,入口是AgentSession.executeBash()

两者最终都会走到 bash-executor.ts 中的executeBash()完成非 PTY 执行,但只有工具调用面会执行命令规范化、拦截(interception)、受管后台作业处理和工具渲染逻辑。在配置中设置bash.enabled: false可以把模型可见的bash工具从工具注册表移除,但不会影响用户 bang 命令或 RPCbash请求。

核心源文件布局如下(均来自 docs/tools/bash.md 的 Source 清单):

文件职责
packages/coding-agent/src/tools/bash.ts工具入口:输入处理、拦截检查、路径选择、结果/错误映射、渲染器
packages/coding-agent/src/prompts/tools/bash.md面向模型的工具提示词
packages/coding-agent/src/tools/bash-interactive.tsPTY/TUI 执行路径
packages/coding-agent/src/tools/bash-interceptor.ts拦截"该用专用工具而非 shell"的命令
packages/coding-agent/src/tools/bash-skill-urls.ts内部 URL(skill://local://等)展开为本地路径
packages/coding-agent/src/tools/bash-pty-selection.tscanUseInteractiveBashPty()判定是否可走本地 PTY 叠加层
packages/coding-agent/src/tools/gh-cache-invalidation.ts对变更类gh issue/gh pr子命令使github-cache行失效
packages/coding-agent/src/exec/bash-executor.ts非 PTY shell 执行器
packages/coding-agent/src/session/streaming-output.ts输出 tail 缓冲、截断、artifact 溢出
packages/coding-agent/src/tools/tool-timeouts.ts超时常量与钳制逻辑
packages/coding-agent/src/config/settings-schema.ts默认拦截器规则

更底层的 shell 会话复用、快照、原生超时行为见配套文档 docs/bash-tool-runtime.md。

二、输入参数详解

工具输入由 bash.ts 中的 schema 定义,字段如下:

字段类型必填说明
commandstring要执行的 shell 命令文本。仅当cwd未提供时,前导的cd <path> && ...会被改写为cwd字段并从命令中剥离
envRecord<string, string>额外环境变量。键必须匹配^[A-Za-z_][A-Za-z0-9_]*$,否则工具抛错。值会经过内部 URL 展开,并作为环境变量值(而非 shell 文本)传入
timeoutnumber超时秒数。默认3000表示禁用截止时间。正值先受tools.maxTimeout(若为正)限制,再钳制到 Bash 区间1..3600
cwdstring工作目录,经resolveToCwd相对session.cwd解析;必须存在且为目录
ptyboolean请求 PTY 模式,默认false。仅当pty: truePI_NO_PTY !== "1"且工具上下文存在 UI 时才真正使用 PTY
asyncboolean请求后台执行。仅当会话开启了async.enabled时该字段存在。立即返回 job id 而不是等待;它不改变有效截止时间,包括timeout: 0禁用的截止时间

几个在源码中可直接验证的细节:

  • env 键校验:bash.ts 中BASH_ENV_NAME_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/,非法键会抛出ToolError("Invalid bash env name: <key>")
  • cd前缀改写execute()在 bash.ts#L1027-L1033 调用extractLeadingCdTarget(),只捕获单个路径 token;涉及重定向、参数或 shell 展开的写法(如cd /tmp 2>/dev/null && ...)不会被吸收进结构化cwd,仍留给 shell 处理。改写仅限首行的顶层&&
  • timeout 常量:tool-timeouts.ts 中TOOL_TIMEOUTS.bash = { default: 300, min: 1, max: 3600 }clampTimeout()的语义是:tools.maxTimeout作为正的全局上限先钳制解析值(包括省略timeout走默认值的路径),再套用每工具的min/maxmaxTimeout <= 0表示不设全局上限。

三、输出结构与结果元数据

工具返回单个text内容块加上可选的details,四种形态:

前台成功

  • content[0].text:命令输出;命令无任何输出时为(no output)
  • details.timeoutSeconds:经全局/每工具钳制后的有效正超时;timeout: 0时改为details.timeoutDisabled: true
  • details.requestedTimeoutSeconds:请求的正超时与有效超时时限时出现。
  • details.wallTimeMs:本地/客户端终端完成的运行所耗挂钟毫秒数。
  • details.terminalId:执行被路由到客户端终端桥接时出现。
  • details.exitCode:命令以非零码完成时出现。
  • details.timedOut: true:本地/PTY 超时结果。
  • details.meta.truncation:输出在内存中被截断时出现;若完整输出已溢出到 artifact,还包含artifactId
  • 非零退出码和本地/PTY 超时返回标记isError的工具结果;确定性非零输出以Command exited with code <n>结尾。

后台启动(async: true或自动后台化)

  • content[0].text:可选的预览尾部与提示,随后是Backgrounded as job <id>; result will be delivered automatically.
  • details.async{ state: "running", jobId, type: "bash" }

后台进度 / 完成

  • 通过onUpdate/ 异步作业管理器投递,而不是初始返回值。
  • 运行中更新只包含尾部文本,且details.async.state: "running"仅在作业被视为已后台化后出现。
  • 完成/失败更新携带最终文本与details.async.state: "completed" | "failed";非零退出或超时被记录为失败的后台作业。

失败

  • 取消、缺失退出状态、校验失败、被拦截的命令、客户端终端桥接超时,均抛出ToolError/ToolAbortError

注意:stdout 与 stderr 在模型看到之前已被合并;确定性非零退出码会追加到返回的错误结果文本末尾,形式为Command exited with code <n>

四、命令策略:bash.patternsbashInterceptor.patterns

有两套相互独立的设置可以阻止 Bash 子进程启动。它们目的不同、在工具调用生命周期中作用点也不同:

设置目的规则语法命中时的结果
bash.patterns命令级执行策略*通配符的字面文本放行、请求人工审批或拒绝该调用
bashInterceptor.patterns优先使用专用工具而非 BashJavaScript 正则、可选 flags、工具名与消息返回 Bash 工具错误,指示模型改调指定专用工具

4.1bash.patterns:审批策略

bash.patterns用于"无论是否存在其他工具都能完成,该命令都必须被允许、人工确认或拒绝"的场景。规则有序,第一条匹配的规则生效。每条规则由matchglob 与approvalallow/prompt/deny)组成:

bash: patterns: - match: "git *" approval: allow - match: "curl *" approval: prompt - match: "rm -rf *" approval: deny

匹配语义在 bash.ts 中实现,要点:

  • denyBashTool.execute()运行之前即中止调用,包括yolo模式
  • prompt显示审批请求,只有被接受的请求才会进入BashTool.execute()
  • allow可以为简单命令降低审批层级,但不能批准复合命令:例如match: "git *"不会批准git status && rm -rf build。源码层面,allow规则要求 glob 匹配整个命令,且命令含 shell 控制字符(;&|$、反引号等,含引号内的可重解释形态)时直接不适用;
  • denyprompt同时检查完整命令每个 shell 命令段(复用共享 shell tokenizer,识别;&&|||&、子 shell、换行等全部边界),因此match: "rm -rf *"能捕获cd /tmp && rm -rf build

该设置服务于安全与用户控制,对没有合适替代工具的命令(破坏性删除、网络访问、部署脚本、项目私有脚本)尤其有用。

另外,bash.ts#L177-L222 内置了CRITICAL_BASH_PATTERNS一组"安全关键"正则(刻意保持收紧),覆盖:递归销毁绝对路径(各种 flag 顺序的rm -rf /--no-preserve-root)、任意sudo rmchmod -R/chown -R指向/、fork 炸弹、写块设备/mkfs/dd/shred/cryptsetup、覆写/etc/passwd/etc/shadow/etc/sudoerscurl|wget管道进 shell、bash <(curl …)/eval $(curl …)等远端拉取即执行形态、kill -9 1shutdown/reboot/halt/init 0nc -e/nc -c网络 shell。这些检查先于用户模式策略执行,且对原始输入与规范化输入、整行与各命令段同时生效——允许前缀不能掩盖后续的关键段。

4.2bashInterceptor.patterns:专用工具路由

bashInterceptor可选启用(opt-in)的路由层,bashInterceptor.enabled默认false。它针对"技术上合法、但用现成专用工具表达更好"的命令。每条规则是一个正则,附带替代工具名与展示给模型的说明消息:

bashInterceptor: enabled: true patterns: - pattern: '^\s*(cat|head|tail)\s+' tool: read message: "Use the read tool instead; it handles binary files and provides better context." - pattern: '^\s*(grep|rg)\s+' tool: grep message: "Use the grep tool instead; it respects .gitignore and returns structured results."

关键行为(实现在 bash-interceptor.ts 的checkBashInterception()):

  • 只有当规则的tool在当前会话可用时规则才生效(检查ctx.toolNames)。若read被禁用,指向readcat规则不会阻止 Bash 调用。这使拦截器是"尽力而为的能力偏好",而不是执行安全边界
  • 无效的自定义正则在compileRules()中被静默跳过;
  • 命中时抛出ToolError,消息为Blocked: <rule.message>并附上原始命令。

片段匹配算法:为兼容既有自定义正则,拦截器总是先检查完整原始命令;然后检查由未加引号、未转义的&&||;|&或换行分隔的原始扁平命令段(排除通过未加引号||&消费上一级 stdout 的段——见interceptionCandidates());最后检查剥离前导NAME=value赋值后的片段。因此锚定规则^\s*git\s+commit\b能同时命中:

git add file && git commit -m "message" GIT_AUTHOR_NAME=Dev git commit -m "message"

printf 'x\n' | grep x中的grep x不会被视为拦截候选:它读取的是管道 stdin,路径类专用工具无法提供,只有独立命令或管道首段才会匹配。管道后空行与仅注释的续行保持该上下文;引号内、转义与注释文本不算命令。heredoc、参数展开、命令替换、反引号、分组与错误引号只保留完整命令检查——拦截器刻意不做完整 shell 解析。

内置默认规则DEFAULT_BASH_INTERCEPTOR_RULES,见 settings-schema.ts#L409):

正则目标路由到
cat/head/tail/less/moreread
grep/rg/ripgrep/ag/ackgrep
-name/-iname/-type/--type/-globfind/fd/locateglob
sed -iperl -iawk -i inplaceedit
带文件重定向的echo/printf/cat <</dev/null等设备目标除外,fd 复制>&2不匹配)write
nohup、行尾裸&hubop:"start"
bun/npm/pnpm/yarn dev|startvitenext devnuxt devnodemonlldbgdbtail -f、未 detach 的docker compose uphub(服务/调试器)
bun/npm/pnpm/yarn <script>cargo watchwatchexecpytestvitestjesttsc且带--watch/-whub(watch 模式)

4.3 两套策略的交互与选择指南

  • 审批策略在执行前解析:命中的bash.patternsdeny永远不会到达拦截器;prompt只有在用户接受审批请求后才到达拦截器;
  • 若已接受的调用又命中拦截器规则,Bash 调用依然不会运行,模型收到路由错误并应改调专用工具;
  • 避免对同一操作在两处都配置,除非你有意要这种"两步"行为。例如cat *prompt规则加上启用的catread拦截器,会先请求用户批准 Bash,随后拒绝 Bash 并要求模型使用read

选择原则:

  • 问题是"这条命令能否执行" → 用bash.patterns
  • 问题是"该操作应由哪个工具完成" → 用bashInterceptor.patterns

此外要理解一个边界(来自 docs/bash-tool-runtime.md):bash.patterns只约束bash工具本身,无法约束eval等可通过子进程起 shell 的工具——同一条命令走evaldeny规则不生效。要跨两个面加固破坏性命令,需要为eval另行配置tools.approval.evalpromptdeny)。审批也不意味着隔离:批准后进程仍拥有 shell 的完整文件系统、网络与子进程访问。

五、执行管线:从 execute() 到子进程

BashTool.execute()的完整流程(编号继承自 docs/tools/bash.md 的 16 步管线,关键步骤均与 bash.ts#L1004-L1144 源码对应):

  1. 读取command,校验envtimeout默认300
  2. cwd缺失,把前导cd <path> && ...改写为结构化cwd字段并剥离该前缀;
  3. 若请求了async: trueasync.enabled为关,抛ToolError,任何执行都不会发生;
  4. bashInterceptor.enabled开启,对原始命令cd 剥离后命令两种形态各跑一遍checkBashInterception()(每形态内:完整输入 → 扁平段 → 去前导赋值片段)。命中的启用规则在 URL 展开或执行之前抛错;
  5. expandInternalUrls()改写command、每个env值以及形如协议的cwd中的内部 URL。命令替换会做 shell 转义;envcwd替换使用原始文件系统/字符串值(noEscape: true),因为它们不会被插入 shell 文本;
  6. resolveToCwd()相对session.cwd解析cwdfs.stat()验证目标存在且是目录;
  7. timeout: 0禁用截止时间;否则clampTimeout("bash", requested, tools.maxTimeout)先应用正全局上限(若配置),再套TOOL_TIMEOUTS.bashmin: 1max: 3600)。发生钳制时,#buildCompletedResult()/#buildBackgroundStartResult()追加一条提示行;
  8. 执行路径分叉
    1. async: true#startManagedBashJob()注册会话异步作业并立即返回;
    2. 非 PTY 且bash.autoBackground.enabled开启、异步作业管理器未达运行上限、且无客户端终端桥接可用(两者同时满足时桥接优先)→ 启动受管作业,最多等待min(thresholdMs, timeoutMs - 1000),要么返回已完成结果,要么把运行转为后台作业;
    3. 非 PTY 客户端终端桥接:会话声明了 terminal 能力且pty为 false → 创建远端终端、流式/轮询当前输出、完成后释放终端;
    4. 其余走前台执行;
  9. 前台非 PTY 且无客户端终端时调用 bash-executor.ts 的executeBash(),该路径自行完成 direnv/devenv 预检;
  10. 前台 PTY 与客户端终端路径在分发前于BashTool内执行同样的 direnv 预检。bash.direnv: "auto"(默认)下,被允许的.envrc可把环境变量变更合并进命令;"off"禁用。bash.direnvLoadTimeoutMs默认30_000,正的命令超时也会约束预检时长;
  11. 本地非 PTY 与 PTY 路径在session.allocateOutputArtifact可用时先分配输出 artifact,artifact 路径/ID 传入 sink,大输出可溢出到磁盘;
  12. executeBash()加载 shell 配置、可选 shell 快照与 shell minimizer 设置,然后通过持久原生Shell会话或一次性executeShell()运行(详见 docs/bash-tool-runtime.md);
  13. runInteractiveBashPty()创建PtySession,叠加 xterm 支撑的控制台 UI,把用户按键输入转发进 PTY,经OutputSink捕获输出,并在关闭/销毁时杀掉 PTY;
  14. 客户端终端桥接模式调用session.getClientBridge().createTerminal(...),发出terminalId更新,轮询输出直至退出/超时/中止,把信号退出映射为137,并在finally中释放句柄;
  15. 完成时#buildCompletedResult()按需格式化(no output),附加来自输出摘要的截断元数据、耗时/超时/退出提示,并在返回前复查未结束状态;
  16. 本地/PTY 超时结果变为带details.timedOutisError结果;客户端终端超时与取消/缺失退出状态路径在可获取捕获输出的情况下抛错。

面向模型的提示词

prompts/tools/bash.md 定义了模型看到的 bash 工具说明,其中约束直接影响模型行为:仅在"单个二进制或计算事实的短管道"(wc -lsort | uniq -cdiff)时使用 bash;内联脚本、heredoc、$(…)、复杂控制流应交给eval或专门工具/入库脚本;用cwd而不是cd;多行/重引号值用env: { NAME: "…" }pty: true仅用于终端交互(sudossh);顺序依赖命令用一次调用内的&&,独立调用可并发;永不使用 shellgrep/rg/ls/find;输出会被捕获、截断并以artifact://<id>链接,无需head/tail;服务、watcher、调试器、REPL 必须用hubop:"start")。该提示词还会在启用内建 uutils 时列出进程内可用的辅助命令(mkdirwcsortdiffjq等),并说明async: true只是推迟有限命令的结果交付、不会延长timeout

六、执行模式与变体

#模式触发条件说明
1前台非 PTY 本地无客户端终端桥接时的默认路径使用executeBash();经streamTailUpdates()TailBuffer(DEFAULT_MAX_BYTES)流式推送仅尾部更新
2前台非 PTY 客户端终端session.getClientBridge()?.capabilities.terminal为 true、存在createTerminalpty为 false以轮询更新流式输出当前终端内容,带details.terminalId;执行相同超时/中止行为后释放终端句柄
3前台 PTYpty: true、UI 上下文、PI_NO_PTY !== "1"runInteractiveBashPty()+PtySession叠加层;支持交互输入,叠加层中按Esc杀掉会话
4显式后台作业async: trueasync.enabledsession.asyncJobManager注册作业并立即返回{ state: "running", jobId }timeout: 0使作业没有工具强加的截止时间
5自动后台化非 PTY 作业bash.autoBackground.enabled、无 PTY/客户端终端桥接、作业管理器未达运行上限先按前台受管作业启动,存活超过等待窗口即后台化;达到容量上限时 Bash 回退到直接前台执行
6被拦截命令拦截器命中且替代工具可用不创建子进程;返回指向readgrepglobeditwriteToolError

PTY 在 non-UI 上下文与PI_NO_PTY=1时被忽略(由canUseInteractiveBashPty()把关),工具回退到非 PTY 执行并追加pty requested but unavailable in this environment; ran without a terminal提示。

七、输出处理:截断、溢出与最小化

  • 内存 tail 上限50 * 1024字节(streaming-output.ts 中的DEFAULT_MAX_BYTES)。超出后 sink 只在内存保留尾部窗口并标记截断;
  • 流式回调节流executeBash()中启用流式时,相邻两次onChunk调用间隔50ms
  • TUI 折叠预览:在 Agent UI 中内联渲染时10视觉行(bash.ts 的BASH_DEFAULT_PREVIEW_LINES)——这是渲染器上限,不是工具输出上限;
  • artifact 溢出:截断发生时若分配成功,完整输出写入 artifact,截断元数据带artifactId,工具包装层自动附加模型可见的恢复提示(如Read artifact://<id> for full output);
  • shell 最小化器:非 PTY 执行把 minimizer 设置传入原生Shell会话;当最小化器重写冗长输出时,可见文本被替换为最小化文本,若onMinimizedSave持久化了原始文本,会追加[raw output: artifact://<id>]页脚(原始文本存为独立的bash-originalartifact)。

八、限制与上限汇总

出处
默认超时300stool-timeouts.tsTOOL_TIMEOUTS.bash.default
timeout: 0禁用命令截止时间
正超时钳制可选全局上限tools.maxTimeout0表示不设全局上限),随后是 Bash 区间1..3600s同上
自动后台默认阈值60_000ms(bash.ts 的DEFAULT_AUTO_BACKGROUND_THRESHOLD_MS,来自 async 模块),存在截止时间时进一步压到timeoutMs - 1000;截止时间被禁用则阈值不受压
非 PTY 执行器定时器有截止时间时在max(1_000, timeoutMs)处挂宿主侧定时器,并把相同正超时传给原生运行;timeout: 0不传截止时间。超时的持久 shell 会话会被隔离(quarantine)bash-executor.ts
内存 tail 上限50KBstreaming-output.tsDEFAULT_MAX_BYTES
流式回调节流50msexecuteBash()
TUI 折叠预览10视觉行BASH_DEFAULT_PREVIEW_LINES

九、副作用清单

  • 文件系统fs.stat()校验cwd;可能为完整本地输出(bash)与最小化器保留的原始输出(bash-original)分配并写入 artifact 文件;expandInternalUrls(..., { ensureLocalParentDirs: true })在执行前为local://路径创建父目录;
  • 子进程 / 原生绑定 / 客户端终端:非 PTY 本地执行使用@oh-my-pi/pi-natives的原生 shell(Shell.run()executeShell());PTY 使用原生PtySession.start();客户端终端模式把进程执行委托给已连接客户端的 terminal 能力;
  • 会话状态:读取 async、auto-background、拦截器、direnv、全局超时上限、工具可用性与 shell 配置;为显式/自动后台运行向session.asyncJobManager注册作业;用session.getSessionId()隔离 shell 复用与异步会话键;用session.allocateOutputArtifact()分配溢出文件;命令含变更类gh issue/gh pr子命令时,在执行前失效github-cache行(invalidateGithubCacheForBashCommand),使后续issue:///pr://读到变更后的状态;
  • 用户可见提示 / 交互 UI:PTY 模式打开标题为Console的 TUI 叠加层并转发输入;后台启动消息说明结果完成时会自动投递,且在此之前可用hub工具等待;
  • 后台工作 / 取消:async 与 auto-background 作业在初始工具返回后继续运行,直到完成、取消或截止时间(除非timeout: 0禁用了它);取消会中止原生运行,PTY 叠加层关闭也会杀掉 PTY。

十、错误处理一览

输入校验

  • 非法 env 键 →ToolError("Invalid bash env name: <key>")
  • 禁用时请求 async →ToolError("Async bash execution is disabled...")
  • 缺少异步作业管理器 →ToolError("Background job manager unavailable for this session.")
  • cwd缺失/非法 →ToolError("Working directory does not exist: ...")ToolError("Working directory is not a directory: ...")(对应 bash.ts#L1100-L1109)。

拦截器

  • 命中命令 → 附Blocked: <rule.message>与原始命令的ToolError
  • 非法拦截器正则在compileRules()中被静默跳过。

内部 URL 展开

  • 不支持的 scheme、未知 skill、路径穿越、缺少路由支持、路由解析失败,均从 bash-skill-urls.ts 抛出ToolError

执行

  • 非零退出 → 标记isError的工具结果,带details.exitCode,文本以Command exited with code <n>结尾;
  • 缺失退出码 → 抛出ToolError("Command failed: missing exit status")
  • 超时 → 本地/PTY 执行返回isError结果且details.timedOut: true并附超时提示;客户端终端桥接在杀掉终端并尝试最后一次输出读取后抛出ToolError;受管后台执行把两种形态都记录为失败作业;
  • 用户中止 → 调用方 signal 被中止时抛ToolAbortError
  • artifact 分配/保存失败在saveBashOriginalArtifact()OutputSink.#createFileSink()中被吞掉,执行在没有该 artifact 的情况下继续。

十一、进阶行为与实战提示

  • 并发模型BashTool设置strict = trueconcurrency按调用解析——pty: true"exclusive"(占用终端 UI),其余为"shared",因此一条 assistant 消息中多个非 PTY bash 调用可并行。并行调用在同一 shell 会话键上重叠时,第一个调用拥有持久Shell,其余在隔离的一次性 shell 中运行(见 bash-executor.ts 的shellSessionsInUse);
  • shell 会话复用executeBash()以(shell 路径、配置前缀、快照路径、序列化 env、可选会话键、minimizer 配置)为键缓存原生Shell实例;工具调用路径传sessionKey: session.getSessionId()。会话级 key 按会话隔离复用;无 key 时回退到 shell 配置/快照/env;
  • 非交互环境加固:非 PTY 运行经buildNonInteractiveEnv()NON_INTERACTIVE_ENVenv合并(分页器禁用PAGER=cat、编辑器提示禁用、TERM=dumbGIT_TERMINAL_PROMPT=0CI=true等,细节见 docs/bash-tool-runtime.md);PTY 运行则继承用户环境并在自定义env值之前前置TERM=xterm-256color,让编辑器、分页器与 TUI 表现如正常终端;
  • URL 展开转义差异command中的替换做 shell 转义;envcwd使用noEscape: true,因为它们是环境变量值/文件系统路径而非 shell 文本;
  • 拦截器边界checkBashInterception()仅在规则tool名出现在ctx.toolNames中时才阻止;它是向专用工具的尽力路由,不是 shell 安全策略——heredoc、参数展开、命令替换、反引号、分组与错误引号只接受整输入检查;
  • direnvbash.direnv默认"auto"且遵守 direnv 允许列表,未被允许的.envrc不执行;设"off"可绕过预检;bash.direnvLoadTimeoutMs控制冷加载预算。

综上,oh-my-pi 的bash工具是一套分层设计:审批策略(bash.patterns+ 内置关键模式)回答"能否执行",拦截器(bashInterceptor.patterns)回答"该谁执行",执行层再按 PTY/桥接/后台/前台分派到不同后端,并由OutputSink统一处理截断与溢出。配置时按此分层思考,即可在不牺牲安全性的前提下获得可预测的命令执行行为。

【免费下载链接】oh-my-pi⌥ Coding agent with the IDE wired in项目地址: https://gitcode.com/GitHub_Trending/oh/oh-my-pi

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询