Skip to content

[FEATURE]: Unify shell initialization behavior between user shell and agent bash tool #17792

Closed

Description

@bakabaka9405

Feature hasn't been suggested before.

  • I have verified this feature I'm about to request hasn't been suggested before.

Describe the enhancement you want to request

Summary

There is an inconsistency between the user-invoked shell (!) and the agent bash tool.
At the moment:

  • the user ! shell loads shell init files such as ~/.bashrc
  • the agent bash tool does not
    As a result, the same command can work in the user shell but fail in the agent shell because functions, aliases, exports, or PATH changes from shell init are only available in one path.

Reproduction

Example ~/.bashrc:

myfunc() {
  echo ok
}
export -f myfunc

Then compare:

  1. Run myfunc through the user shell (!)
  2. Run the equivalent command through the agent bash tool
    Actual behavior
  • User ! shell can access definitions and environment initialized by shell startup files
  • Agent bash tool cannot

Expected behavior

These two shell execution paths should behave consistently.
Possible acceptable outcomes:

  • both load shell init files in the same way, or
  • both avoid loading shell init files, or
  • a config/flag makes the behavior explicit and shared between both paths

Notes

The current implementation appears to use different logic for these paths:

  • packages/opencode/src/session/prompt.ts
    user shell path explicitly sources shell init files for some shells
  • packages/opencode/src/tool/bash.ts
    agent bash tool uses spawn(..., { shell }) without equivalent shell init loading
    This creates surprising differences between manual shell usage and agent-executed shell commands.

Request

Please unify the shell initialization logic between:

  • user ! shell
  • agent bash tool
    If exact unification is not desired, please provide a documented configuration option that controls shell init behavior consistently for both paths.

Activity

  1. added
    discussionUsed for feature requests, proposals, ideas, etc. Open discussion
    on Mar 16, 2026
  2. added
    coreAnything pertaining to core functionality of the application (opencode server stuff)
    on Mar 16, 2026
  3. github-actions commented on Mar 16, 2026

    @github-actions
    Contributor

    This issue might be a duplicate of existing issues. Please check:

    If your issue is substantially the same as one of these, please consider adding detail there instead.

  4. zigmoo commented on Apr 29, 2026

    @zigmoo

    +1 on this feature request — hitting the exact same pain, but with a compounding bug that makes it worse.

    Our specific symptoms

    • Agent: OpenCode (kimi-k2.6) on Linux (Omarchy/Arch)
    • User shell (!): works fine, sources ~/.bashrc, finds all tools
    • Agent bash tool: fails to find any tools installed in PATH via ~/.bashrc

    The compounding bug: literal tilde in inherited PATH

    Not only does the agent bash tool not source ~/.bashrc, but the parent OpenCode/Electron process appears to inject a PATH containing a literal unexpanded ~/.local/bin:

    $ python3 -c 'import os; print([s for s in os.environ["PATH"].split(":") if "~" in s])'
    ['~/.local/bin']

    Bash does not expand ~ in inherited environment variables — only at the moment of export. So that segment is effectively a broken path.

    Evidence: DIL tool directory completely absent from $PATH

    (DIL Distributed Intent Ledger)

    Our ~/.bashrc adds:

    export PATH="$HOME/Documents/dil_agentic_memory_0001/_shared/scripts/bin:$PATH"

    After agent spawns bash -c:

    $ which task_tool
    # "no task_tool in (...)"
    
    $ source ~/.bashrc && which task_tool
    # /home/moo/Documents/dil_agentic_memory_0001/_shared/scripts/bin/task_tool

    Relationship to other issues

    Why Claude/Codex work

    They appear to spawn bash as a login shell (bash -l -c) or explicitly source ~/.bashrc, so PATH additions and function definitions are available to the agent.

    Request

    Please consider:

    1. Spawning agent bash as a login shell (bash -l -c '...') on Linux/macOS, OR
    2. Explicitly expanding tildes in inherited PATH before spawning, OR
    3. Sourcing shell init files before agent command execution.

    This would fix the disjoint between ! shell (works) and agent bash tool (broken) that #17792 identifies.

    PS: Thanks to https://github.com/bakabaka9405 for the existing Issue to Work With!

  5. bakabaka9405 commented on Apr 30, 2026

    @bakabaka9405
    Author

    I found a temporary workaround for the current behavior by using an opencode hook to inject my PowerShell profile before every agent bash tool execution.

    // .opencode/plugins/source-before-bash.js
    export const SourceBeforeBash = async () => {
      return {
        "tool.execute.before": async (input, output) => {
          if (input.tool !== "bash") return
    
          const command = output.args?.command
          if (!command || typeof command !== "string") return
    
          const sourceFile = "C:/Users/<Username>/Documents/PowerShell/Microsoft.PowerShell_profile.ps1"
    
          if (command.includes("$env:__BASH_AUTO_INJECT")) return
    
          output.args.command =
            `. '${sourceFile}'; $env:__BASH_AUTO_INJECT = 1; ${command}`
        },
      }
    }

    This makes the agent bash tool load the same profile initialization that I expect in my normal shell session, so aliases/functions/PATH changes from my PowerShell profile become available to agent-executed commands as well.

    The $env:__BASH_AUTO_INJECT = 1 marker is necessary as a sentinel. It prevents the hook from injecting the same source command repeatedly if a command is already wrapped. It also helps when the injected command leaks into the visible tool history and the agent later copies or imitates the previous command: the hook can detect the marker and avoid a second injection. Without this guard, commands can become nested like:

    . 'profile.ps1'; . 'profile.ps1'; . 'profile.ps1'; <actual command>

    This workaround is functional, but it has two drawbacks:

    1. The injected prefix is currently visible in the command shown to the user and/or retained in the agent-visible history.
    2. That increases token usage and can encourage the agent to learn or reproduce implementation details that should ideally remain a transport/runtime concern.

    This is very close to the motivation behind #5321, where displayInput would allow a plugin to execute a wrapped command while displaying the original, unwrapped command. I agree with that direction. The hook/plugin layer would be much safer and cleaner if opencode officially supported a way for tool.execute.before hooks to distinguish between:

    • the command actually executed by the runtime, and
    • the command shown in the UI / persisted into agent-visible history.

    Related work also appears in #6927, which mentions #5321 as related to tool input/output display behavior.

    So while this hook is a usable temporary workaround, I would still prefer an official solution that either:

    • unifies shell initialization between user ! shell and agent bash tool directly, or
    • provides a documented hook/display API so wrappers can safely hide injected runtime prefixes.

    This would improve security, reduce token usage, and avoid training the agent to copy internal wrapper commands.

  6. removed
    discussionUsed for feature requests, proposals, ideas, etc. Open discussion
    coreAnything pertaining to core functionality of the application (opencode server stuff)
    on May 3, 2026
  7. CresentMoon commented on Jun 14, 2026

    @CresentMoon

    As a Simplified Chinese user on Windows, I'd like to add our pain point.

    On Windows, the system code page defaults to 936 (GBK), but most modern development tools expect UTF-8 (65001). The typical fix is adding chcp 65001 to the PowerShell profile. However, since the agent bash tool doesn't load the PowerShell profile, Chinese characters in command output become garbled. This significantly hurts the experience for Chinese-speaking developers.

    Note that enabling the "Beta: Use Unicode UTF-8 for worldwide language support" option in Windows region settings is not a viable workaround for Chinese users — it breaks text rendering in many legacy applications, causing garbled characters in non-Unicode programs. This is a well-known compatibility issue reported by many Chinese users.

    A unified shell init behavior (or at least making the ! shell and agent bash tool consistent) would resolve this and make OpenCode much more accessible to the Chinese developer community.

  8. Xarianne commented on Jul 20, 2026

    @Xarianne

    I have ran into this issue as well (just making the interest in this fix known from another user.)

  9. ch-arslanahmad commented on Sep 4, 2026

    @ch-arslanahmad

    For anyone waiting on this, here's a working workaround on Linux using BASH_ENV.

    1. Create ~/.config/opencode/shell-init.sh with your aliases and env:
    #!/bin/bash
    # Source whatever files define your aliases and env.
    # Only load non-interactive-safe stuff here.
    # Skip interactive tools like starship, zoxide, mise -- they break in dumb terminals.
    
    [ -f "$HOME/.bash_aliases" ] && source "$HOME/.bash_aliases"
    [ -f "$HOME/.bash_env" ] && source "$HOME/.bash_env"
    1. Create ~/.config/opencode/shell-wrapper.sh (replace path):
    #!/bin/bash
    export BASH_ENV=/home/youruser/.config/opencode/shell-init.sh
    exec /usr/bin/bash "$@"
    1. In opencode.json:
    { "shell": "/home/youruser/.config/opencode/shell-wrapper.sh" }

    4. chmod +x both files, restart OpenCode.


    Customizing shell-init.sh: Source wherever your aliases live. Locations for me:

    • ~/.bash_aliases -- standalone alias file
    • ~/.bash_env -- environment variables
    • ~/.profile or ~/.bash_profile -- PATH, login exports
    • Your distro's default alias file (e.g. /etc/skel/.bash_aliases)

    Avoid sourcing full ~/.bashrc, it usually has interactive-only stuff (prompts, completions) that errors in non-TTY context.


    Why 2 files: combining them causes an infinite loop since bash sources BASH_ENV on start.

    BASH_ENV is auto-sourced by bash in non-interactive mode in OpenCode, bypassing the ~/.bashrc interactive guard (available by default) without removing it.

  10. neriousy commented on Oct 20, 2026

    @neriousy
    Member

    Thanks for the report — starting with OpenCode 2.0.0, user shell commands and the agent's shell tool share non-interactive startup behavior rather than explicitly sourcing different shell profiles. No opt-in is needed: ! commands and agent shell commands both use this behavior, so interactive aliases/functions should not be assumed available. Update with opencode upgrade or npm i -g @opencode/cli@latest (desktop: update the app). Please comment or reopen if the two paths still initialize differently on that version.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions