Skip to content

fix: write SHELLCHECK_PATH to .zshenv for non-interactive shell coverage#2937

Merged
marcusquinn merged 1 commit intomainfrom
bugfix/shellcheck-zshenv-fix
Mar 5, 2026
Merged

fix: write SHELLCHECK_PATH to .zshenv for non-interactive shell coverage#2937
marcusquinn merged 1 commit intomainfrom
bugfix/shellcheck-zshenv-fix

Conversation

@marcusquinn
Copy link
Owner

Summary

  • Fixes the recurring shellcheck memory explosion (17.8 GB across 73 processes today) by writing SHELLCHECK_PATH to ~/.zshenv in addition to .zshrc
  • .zshenv is sourced by ALL zsh processes (interactive and non-interactive), ensuring the shellcheck-wrapper is visible to OpenCode's bash-language-server child processes

Problem

PR #2918 (GH#2915) added shellcheck-wrapper.sh and configured SHELLCHECK_PATH in .zshrc and .bash_profile. But .zshrc is only sourced for interactive shells. OpenCode spawns bash-language-server as a non-interactive child process, so SHELLCHECK_PATH was never set — the wrapper was completely bypassed.

The bash-language-server hardcodes --external-sources in every shellcheck invocation. Without the wrapper stripping this flag, shellcheck follows all source directives recursively across 460+ scripts, causing exponential memory growth per invocation.

Fix

Add .zshenv as Layer 2 in setup_shellcheck_wrapper():

  1. launchctl setenv (macOS) — GUI-launched apps (current boot only)
  2. .zshenv — ALL zsh processes including non-interactive (persists across reboots) [NEW]
  3. Shell rc files (.zshrc, .bash_profile) — interactive terminals

Related

The shellcheck-wrapper.sh (GH#2915) was only configured in .zshrc and
.bash_profile, which are only sourced for interactive shells. OpenCode
spawns bash-language-server as a non-interactive child process, so
SHELLCHECK_PATH was never set — the wrapper was bypassed entirely.

This caused the same runaway shellcheck memory explosion (17.8 GB across
73 processes) that GH#2915 was supposed to fix.

Fix: add .zshenv as Layer 2 in setup_shellcheck_wrapper(). .zshenv is
sourced by ALL zsh processes (interactive and non-interactive), ensuring
the wrapper is visible to LSP child processes.
@gemini-code-assist
Copy link

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request addresses a critical memory consumption problem with shellcheck when used in non-interactive zsh environments, specifically within tools like bash-language-server. By adjusting how the SHELLCHECK_PATH environment variable is set, the change guarantees that the shellcheck-wrapper is always invoked, thereby preventing shellcheck from recursively processing external sources and consuming excessive memory.

Highlights

  • Shellcheck Memory Fix: Resolved a recurring shellcheck memory explosion issue by ensuring its wrapper is correctly sourced in all zsh processes, including non-interactive ones.
  • SHELLCHECK_PATH Configuration: Modified the setup_shellcheck_wrapper function to write SHELLCHECK_PATH to ~/.zshenv, making it accessible to non-interactive zsh child processes.
  • Non-Interactive Shell Support: Ensured the shellcheck-wrapper is visible to tools like bash-language-server which operate in non-interactive zsh environments, preventing the wrapper from being bypassed and causing excessive memory usage.
Changelog
  • setup-modules/shell-env.sh
    • Updated comments to detail the new three-layer approach for setting SHELLCHECK_PATH, explicitly mentioning .zshenv for non-interactive zsh processes.
    • Implemented logic to check for and, if necessary, append the SHELLCHECK_PATH export line to ~/.zshenv.
    • Re-ordered the layers in the setup_shellcheck_wrapper function's comments to reflect the new .zshenv layer.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 5, 2026

Warning

Rate limit exceeded

@marcusquinn has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 28 minutes and 21 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: f65ec1c3-e725-4bc1-b9ea-e2c7471a7280

📥 Commits

Reviewing files that changed from the base of the PR and between 682383d and fb05d66.

📒 Files selected for processing (1)
  • setup-modules/shell-env.sh
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch bugfix/shellcheck-zshenv-fix

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@marcusquinn
Copy link
Owner Author

@coderabbitai review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 5, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@marcusquinn marcusquinn merged commit 341d310 into main Mar 5, 2026
6 checks passed
@marcusquinn marcusquinn deleted the bugfix/shellcheck-zshenv-fix branch March 5, 2026 17:27
Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request correctly identifies and fixes an issue where SHELLCHECK_PATH was not being set for non-interactive zsh shells by adding the configuration to .zshenv. The logic is sound. The suggestion to improve the robustness of the file check by avoiding error suppression has been retained, as it aligns with the project's guidelines for clearer debugging.

# shells, so SHELLCHECK_PATH set only in .zshrc is invisible to the LSP.
local zshenv="$HOME/.zshenv"
if [[ -f "$zshenv" ]] || command -v zsh >/dev/null 2>&1; then
if grep -q 'SHELLCHECK_PATH' "$zshenv" 2>/dev/null; then

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

While this logic is clever, using 2>/dev/null with grep can mask underlying issues like file permission errors, causing the script to fail on a later line with a less informative error message. A more robust approach is to explicitly check for the file's existence before calling grep. This avoids suppressing potentially important errors and aligns with the project's general rules against blanket error suppression.

Suggested change
if grep -q 'SHELLCHECK_PATH' "$zshenv" 2>/dev/null; then
if [[ -f "$zshenv" ]] && grep -q 'SHELLCHECK_PATH' "$zshenv"; then
References
  1. Avoid using 2>/dev/null to suppress errors on file operations if the file's existence has already been verified by a preceding check (e.g., [[ -f "$file" ]] or an early return). This practice is redundant for 'file not found' errors and can mask other important issues like permissions problems.
  2. Avoid using '2>/dev/null' for blanket suppression of command errors in shell scripts to ensure that authentication, syntax, or system issues remain visible for debugging.

@github-actions github-actions bot added the bug Auto-created from TODO.md tag label Mar 5, 2026
@github-actions
Copy link

github-actions bot commented Mar 5, 2026

🔍 Code Quality Report

�[0;35m[MONITOR]�[0m Code Review Monitoring Report

�[0;34m[INFO]�[0m Latest Quality Status:
SonarCloud: 0 bugs, 0 vulnerabilities, 108 code smells

�[0;34m[INFO]�[0m Recent monitoring activity:
Thu Mar 5 17:44:43 UTC 2026: Code review monitoring started
Thu Mar 5 17:44:43 UTC 2026: SonarCloud - Bugs: 0, Vulnerabilities: 0, Code Smells: 108

📈 Current Quality Metrics

  • BUGS: 0
  • CODE SMELLS: 108
  • VULNERABILITIES: 0

Generated on: Thu Mar 5 17:44:46 UTC 2026


Generated by AI DevOps Framework Code Review Monitoring

@sonarqubecloud
Copy link

sonarqubecloud bot commented Mar 5, 2026

@marcusquinn
Copy link
Owner Author

Follow-up: root cause removed in PR #2939

This PR fixed the .zshenv path for non-interactive shells. PR #2939 goes further — removes source-path=SCRIPTDIR from .shellcheckrc entirely and disables SC1091 globally. Even if the wrapper is bypassed, there's nothing to explode now.

Upstream hazard note: The bash-language-server still hardcodes --external-sources — other opencode/shellcheck users with source-path in their .shellcheckrc will hit the same issue. See anomalyco/opencode#16209.

@opencode-agent
Copy link

opencode-agent bot commented Mar 5, 2026

fatal: couldn't find remote ref bugfix/shellcheck-zshenv-fix

opencode session  |  github run

marcusquinn added a commit that referenced this pull request Mar 6, 2026
…nv.sh

Address PR #2937 review feedback (gemini): grep with 2>/dev/null masks
permission errors and other non-file-not-found failures.

- Line 511: add [[ -f "$zshenv" ]] guard before grep (file may not
  exist when entering via the 'command -v zsh' branch)
- Line 533: remove redundant 2>/dev/null (file existence already
  guaranteed by the check at lines 527-530)

Closes #2955
marcusquinn added a commit that referenced this pull request Mar 6, 2026
…nv.sh

Address quality-debt from PR #2937 review feedback (GH#2955).

Replace all remaining grep 2>/dev/null patterns with either:
- Removal (when file existence is already guaranteed by prior logic)
- Explicit [[ -f ]] guards (when the file may not exist)

This prevents masking permission errors and other non-file-not-found
failures while maintaining correct behaviour for missing files.
marcusquinn added a commit that referenced this pull request Mar 6, 2026
…nv.sh (#3003)

Address quality-debt from PR #2937 review feedback (GH#2955).

Replace all remaining grep 2>/dev/null patterns with either:
- Removal (when file existence is already guaranteed by prior logic)
- Explicit [[ -f ]] guards (when the file may not exist)

This prevents masking permission errors and other non-file-not-found
failures while maintaining correct behaviour for missing files.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Auto-created from TODO.md tag

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant