Skip to content

Fix shell integration not loading on Finder launch - #1974

Open
rerun0510 wants to merge 1 commit into
manaflow-ai:mainfrom
rerun0510:fix/shell-integration-deferred-load
Open

rerun0510 wants to merge 1 commit into
manaflow-ai:mainfrom
rerun0510:fix/shell-integration-deferred-load

Conversation

@rerun0510

@rerun0510 rerun0510 commented Mar 23, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • Fix shell integration not loading when cmux is launched from Finder (double-click / Dock / Spotlight).
  • Root cause: the previous design loaded cmux integration in .zshenv, but tools that reset precmd_functions in .zprofile or .zshrc clobbered the hooks before the first prompt.
  • Fix: keep ZDOTDIR pointing to the integration directory through the full zsh startup sequence and load integration in the .zshrc wrapper — after all user startup files have been processed.
  • Fixes ZDOTDIR set to nonexistent shell-integration directory breaks ~/.zshrc loading #1165

Affected tools

Confirmed with Kiro CLI (formerly Amazon Q / Fig), which resets precmd_functions in .zprofile during full initialization. Any other tool that resets (rather than appends to) precmd_functions during .zprofile or .zshrc processing could cause the same issue. The new design is immune because integration loads after all user startup files.

Why Finder-only?

When launched via reload.sh or open from a terminal, the app inherits environment variables (e.g. Q_TERM) from the parent shell. Some tools skip their full initialization when these variables are present, preserving precmd_functions. From Finder, these variables are absent, triggering a full init that resets the array.

What changed

File Before After
.zshenv Restored ZDOTDIR immediately, loaded Ghostty + cmux integration in always block Saves original ZDOTDIR to _CMUX_ORIG_ZDOTDIR, sources user's .zshenv, keeps ZDOTDIR set to integration dir
.zprofile Fallback shim (never reached) Sources user's .zprofile via _CMUX_ORIG_ZDOTDIR
.zshrc Fallback shim (never reached) Sources user's .zshrc, fixes HISTFILE if still pointing to integration dir (respects custom HISTFILE), loads Ghostty + cmux integration, restores ZDOTDIR
.zlogin Fallback shim (never reached) Not reached — ZDOTDIR is restored in .zshrc so zsh loads the user's .zlogin directly. Wrapper exists as a safety fallback.

Testing

  • Verified on macOS 26.3.1(a) (Build 25D771280a) with Kiro CLI installed.
  • Finder launch: type _cmux_precmd → shell function found. Workspace sidebar updates on cd.
  • reload.sh --tag launch: same result, no regression.
  • open from terminal launch: same result, no regression.
  • Verified HISTFILE points to ~/.zsh_history (not the integration dir).
  • Verified custom HISTFILE (set in user's .zshrc) is preserved after shell startup.
  • Verified ZDOTDIR is unset (or restored to user's original) after shell startup.

Known limitation

During the user's .zshrc execution, $ZDOTDIR still points to the integration directory. If a user's .zshrc references $ZDOTDIR (e.g. source "$ZDOTDIR/.zsh_aliases"), it will resolve to the wrong path. Affected users are likely rare, but the issue would be hard to diagnose. Please consider addressing this separately.

  • Possible fix: temporarily restore ZDOTDIR before sourcing the user's .zshrc, then re-set it afterward.

Demo Video

Kiro is not installed

Directory changes are properly reflected in the workspace.

2026-03-23.13.57.22.mov

Kiro is installed

This is cmux built from the latest main branch

  • Open from Finder
    Directory changes are not reflected in the workspace.
2026-03-23.14.03.19.mov
  • Open from the command
    Directory changes are properly reflected in the workspace.
2026-03-23.14.07.37.mov

The version with this fix

Directory changes are properly reflected in the workspace.

2026-03-23.14.09.59.mov

Summary by cubic

Fixes cmux zsh integration not loading when launched from Finder by keeping ZDOTDIR pinned during startup and moving integration load to the .zshrc wrapper. Prevents tools that reset precmd_functions from clobbering cmux hooks, then restores the user's ZDOTDIR.

  • Bug Fixes
    • .zshenv saves the original ZDOTDIR to _CMUX_ORIG_ZDOTDIR, sources the user’s .zshenv, and defers integration to .zshrc.
    • .zshrc sources the user’s file, loads Ghostty and cmux integration, fixes HISTFILE if it points to the integration dir, then restores ZDOTDIR.
    • .zprofile and .zlogin wrappers source the user’s files from _CMUX_ORIG_ZDOTDIR.

Written for commit ccf948f. Summary will update on new commits.

Summary by CodeRabbit

  • Refactor
    • Improved shell startup handling to consistently source users' shell startup files and better preserve their history location.
    • Reduced unexpected environment variable side effects during startup.
    • Made integration modules load only when explicitly enabled, with safer fallback resolution for integration scripts.

@vercel

vercel Bot commented Mar 23, 2026

Copy link
Copy Markdown

@rerun0510 is attempting to deploy a commit to the Manaflow Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai

coderabbitai Bot commented Mar 23, 2026 •

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

Preserves the user's original ZDOTDIR in _CMUX_ORIG_ZDOTDIR, removes prior compatibility shims that mutated ZDOTDIR, and consistently sources user dotfiles from the preserved location. .zshrc also adjusts HISTFILE and conditionally loads Ghostty/cmux integrations, then restores/unsets ZDOTDIR.

Changes

Cohort / File(s) Summary
Core env / sourcing
Resources/shell-integration/.zshenv
Add _CMUX_ORIG_ZDOTDIR (from GHOSTTY_ZSH_ZDOTDIR or CMUX_ZSH_ZDOTDIR or $HOME), export it, unset injected *_ZSH_ZDOTDIR vars, and always source the user's .zshenv from _CMUX_ORIG_ZDOTDIR (no interactive-only integration loading).
Login-scope shims
Resources/shell-integration/.zprofile, Resources/shell-integration/.zlogin
Remove conditional ZDOTDIR reconstruction/unsetting. Compute _cmux_file from _CMUX_ORIG_ZDOTDIR (fallback $HOME) and source the user's .zprofile/.zlogin only if readable.
Interactive runtime
Resources/shell-integration/.zshrc
Replace ZDOTDIR shim with sourcing from ${_CMUX_ORIG_ZDOTDIR-$HOME}/.zshrc; adjust HISTFILE to point to the preserved dotdir history when appropriate; conditionally load Ghostty and cmux integration scripts; restore/unset ZDOTDIR and clean temporary vars.

Sequence Diagram

sequenceDiagram
    participant Shell as Shell Startup
    participant zshenv as .zshenv
    participant user_zshenv as User .zshenv
    participant zprofile as .zprofile
    participant user_zprofile as User .zprofile
    participant zlogin as .zlogin
    participant user_zlogin as User .zlogin
    participant zshrc as .zshrc
    participant user_zshrc as User .zshrc
    participant Integration as Integrations (Ghostty/cmux)

    Shell->>zshenv: Start (all shells)
    zshenv->>zshenv: Set _CMUX_ORIG_ZDOTDIR (env fallbacks), unset injected vars
    zshenv->>user_zshenv: Source user's .zshenv from _CMUX_ORIG_ZDOTDIR
    user_zshenv-->>zshenv: Return

    Shell->>zprofile: Login shells
    zprofile->>user_zprofile: Source user's .zprofile from _CMUX_ORIG_ZDOTDIR
    user_zprofile-->>zprofile: Return

    Shell->>zlogin: Login shells
    zlogin->>user_zlogin: Source user's .zlogin from _CMUX_ORIG_ZDOTDIR
    user_zlogin-->>zlogin: Return

    Shell->>zshrc: Interactive shells
    zshrc->>user_zshrc: Source user's .zshrc from _CMUX_ORIG_ZDOTDIR
    user_zshrc-->>zshrc: Return
    zshrc->>zshrc: Possibly adjust HISTFILE
    zshrc->>Integration: Conditionally load Ghostty/cmux integrations
    Integration-->>zshrc: Return
    zshrc->>zshrc: Restore/unset ZDOTDIR, cleanup
    zshrc->>Shell: Complete
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Poem

🐰 I nibbled paths and hopped astray,
I found _CMUX_ORIG and chased the fray.
No more lost dotfiles, no ZDOTDIR fog,
A tidy hop through each startup log.
🥕✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately reflects the main change: fixing shell integration loading when cmux is launched from Finder, which is the primary bug addressed in the PR.
Description check ✅ Passed The PR description comprehensively covers the summary (what and why), includes detailed testing procedures with multiple launch scenarios, provides demo videos, and includes a checklist. All key template sections are well-populated.
Linked Issues check ✅ Passed The PR successfully addresses #1165 by shipping shell-integration wrapper files (.zshenv, .zprofile, .zshrc, .zlogin) that properly source user dotfiles and defer integration loading to prevent ZDOTDIR-related issues.
Out of Scope Changes check ✅ Passed All changes are directly scoped to resolving the Finder launch issue and issue #1165. The modifications to four shell files implement the documented fix with no extraneous changes.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

No issues found across 4 files

@greptile-apps

greptile-apps Bot commented Mar 23, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes shell integration not loading when cmux is launched from Finder by deferring the loading of Ghostty and cmux hooks from .zshenv to .zshrc — after all user startup files have been processed. This prevents tools like Kiro CLI that reset precmd_functions in .zprofile or .zshrc from clobbering the integration hooks, which was previously only triggered when environment variables inherited from a parent terminal caused those tools to skip their full initialization.

Key changes:

  • .zshenv now saves the user's original ZDOTDIR as _CMUX_ORIG_ZDOTDIR and keeps ZDOTDIR pointing at the integration directory through the full startup sequence, rather than restoring it immediately.
  • New wrapper files for .zprofile, .zshrc, and .zlogin each source the corresponding user file via _CMUX_ORIG_ZDOTDIR.
  • .zshrc loads integration last (after all user files), fixes HISTFILE if it was set relative to the integration ZDOTDIR, then restores ZDOTDIR and cleans up _CMUX_ORIG_ZDOTDIR.
  • Potential issue: _CMUX_ORIG_ZDOTDIR is unset in .zshrc with the comment "all startup files are done," but .zlogin runs after .zshrc. In practice this is harmless because restoring ZDOTDIR in .zshrc causes zsh to bypass the .zlogin wrapper and load the user's .zlogin directly — but the comment is incorrect and the .zlogin wrapper's reliance on _CMUX_ORIG_ZDOTDIR would silently break if it were ever reached.
  • Known limitation (acknowledged in PR): During user's .zshrc execution, $ZDOTDIR still points to the integration directory rather than the user's real one. Users who reference $ZDOTDIR inside their .zshrc (e.g. source "$ZDOTDIR/.aliases") will get the wrong path.

Confidence Score: 4/5

  • Safe to merge for the targeted Finder-launch regression; one logical inconsistency around .zlogin cleanup ordering is worth addressing but does not break the primary user path.
  • The core fix is correct and well-motivated: deferring integration loading to after .zshrc makes it immune to tools that reset precmd_functions. The .zlogin cleanup-ordering issue (P1 comment) is a real logical inconsistency — the cleanup comment claims all startup files are done when .zlogin has not yet run — but it does not manifest as a user-facing bug under normal zsh behavior because ZDOTDIR restoration causes .zlogin to be loaded directly rather than through the wrapper. The PR also explicitly acknowledges the ZDOTDIR-during-zshrc known limitation. No regressions on the tested paths (Finder, reload.sh, open-from-terminal).
  • .zshrc — premature _CMUX_ORIG_ZDOTDIR cleanup before .zlogin runs; consider adding a clarifying comment or deferring cleanup.

Important Files Changed

Filename Overview
Resources/shell-integration/.zshenv Replaces immediate ZDOTDIR restoration with saving the original path to _CMUX_ORIG_ZDOTDIR, keeping ZDOTDIR pointed at the integration dir so wrapper files control the entire startup sequence. Minor style inconsistency: uses ${_CMUX_ORIG_ZDOTDIR} without a $HOME fallback unlike the other wrappers.
Resources/shell-integration/.zshrc Core of the fix: sources user's .zshrc, fixes HISTFILE if it was set against the integration ZDOTDIR, then loads Ghostty and cmux integration after all user files. ZDOTDIR and _CMUX_ORIG_ZDOTDIR are restored/unset here — but this happens before .zlogin runs, making the .zlogin wrapper's reliance on _CMUX_ORIG_ZDOTDIR unreachable as written.
Resources/shell-integration/.zprofile Simplified from a fallback shim to a purposeful wrapper that sources user's .zprofile via _CMUX_ORIG_ZDOTDIR. Clean and correct.
Resources/shell-integration/.zlogin Simplified from a fallback shim to a wrapper sourcing user's .zlogin via _CMUX_ORIG_ZDOTDIR. In practice this wrapper is bypassed because .zshrc restores ZDOTDIR before .zlogin is looked up — zsh will load the user's .zlogin directly. If the wrapper were somehow reached, _CMUX_ORIG_ZDOTDIR would already be unset, causing a silent fallback to $HOME.

Sequence Diagram

sequenceDiagram
    participant GK as GhosttyKit
    participant ZSH as zsh
    participant ENV as integration/.zshenv
    participant PRO as integration/.zprofile
    participant RC as integration/.zshrc
    participant LOG as integration/.zlogin
    participant UENV as user/.zshenv
    participant UPRO as user/.zprofile
    participant URC as user/.zshrc
    participant ULOG as user/.zlogin

    GK->>ZSH: set ZDOTDIR=integration_dir<br/>set GHOSTTY_ZSH_ZDOTDIR=orig_zdotdir
    ZSH->>ENV: load (ZDOTDIR=integration_dir)
    ENV->>ENV: save _CMUX_ORIG_ZDOTDIR=orig_zdotdir<br/>ZDOTDIR stays → integration_dir
    ENV->>UENV: source user/.zshenv
    ZSH->>PRO: load (ZDOTDIR still=integration_dir)
    PRO->>UPRO: source user/.zprofile<br/>(Kiro CLI may reset precmd_functions here)
    ZSH->>RC: load (ZDOTDIR still=integration_dir)
    RC->>URC: source user/.zshrc<br/>(Kiro CLI may reset precmd_functions here)
    RC->>RC: fix HISTFILE if pointing to integration_dir
    RC->>RC: load Ghostty integration (after user files ✓)
    RC->>RC: load cmux integration (after user files ✓)
    RC->>RC: restore ZDOTDIR=orig_zdotdir<br/>unset _CMUX_ORIG_ZDOTDIR
    Note over ZSH,ULOG: ZDOTDIR now = orig_zdotdir<br/>zsh re-evaluates ZDOTDIR → loads user/.zlogin directly
    ZSH->>ULOG: load user/.zlogin directly (wrapper bypassed)
Loading

Reviews (1): Last reviewed commit: "Fix shell integration not loading on Fin..." | Re-trigger Greptile

Comment on lines +38 to +44
# Restore the user's original ZDOTDIR now that all startup files are done.
if [[ "${_CMUX_ORIG_ZDOTDIR}" == "${HOME}" ]]; then
builtin unset ZDOTDIR
else
builtin export ZDOTDIR="${_CMUX_ORIG_ZDOTDIR}"
fi
builtin unset _CMUX_ORIG_ZDOTDIR _cmux_ghostty _cmux_integ

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P1 _CMUX_ORIG_ZDOTDIR unset before .zlogin runs

The comment says "all startup files are done," but .zlogin executes after .zshrc in the zsh startup sequence (.zshenv → .zprofile → .zshrc → .zlogin). _CMUX_ORIG_ZDOTDIR is being cleaned up here while the .zlogin wrapper still depends on it.

In practice, the .zlogin wrapper is bypassed because zsh re-evaluates ZDOTDIR before loading each startup file — so restoring ZDOTDIR here causes zsh to load the user's .zlogin directly. This is the same mechanism that made .zprofile/.zshrc/.zlogin "never reached" in the old design. The user's .zlogin is therefore loaded correctly in the common case.

However, if _CMUX_ORIG_ZDOTDIR were still needed by the .zlogin wrapper (e.g. on a zsh build that pre-computes startup file paths), the ${_CMUX_ORIG_ZDOTDIR-$HOME} fallback in .zlogin would silently resolve to $HOME, sourcing the wrong .zlogin for any user with a custom ZDOTDIR. The PR description also lists .zlogin as "Sources user's .zlogin via _CMUX_ORIG_ZDOTDIR", which will not work as written once this cleanup has run.

Consider deferring the _CMUX_ORIG_ZDOTDIR unset (and ideally the ZDOTDIR restoration) to .zlogin for login shells, or — since the wrapper is bypassed anyway — document explicitly that .zlogin is always loaded directly after ZDOTDIR is restored here.

Suggested change
# Restore the user's original ZDOTDIR now that all startup files are done.
if [[ "${_CMUX_ORIG_ZDOTDIR}" == "${HOME}" ]]; then
builtin unset ZDOTDIR
else
builtin export ZDOTDIR="${_CMUX_ORIG_ZDOTDIR}"
fi
builtin unset _CMUX_ORIG_ZDOTDIR _cmux_ghostty _cmux_integ
# Restore the user's original ZDOTDIR now that .zshrc integration is done.
# NOTE: .zlogin runs after .zshrc; because ZDOTDIR is restored here, zsh will
# load the user's .zlogin directly (bypassing the wrapper), so cleanup is safe.
if [[ "${_CMUX_ORIG_ZDOTDIR}" == "${HOME}" ]]; then
builtin unset ZDOTDIR
else
builtin export ZDOTDIR="${_CMUX_ORIG_ZDOTDIR}"
fi
builtin unset _CMUX_ORIG_ZDOTDIR _cmux_ghostty _cmux_integ

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@greptile-apps Updated the PR description — .zlogin wrapper is indeed not reached since ZDOTDIR is restored in .zshrc. It exists only as a safety fallback.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

That makes sense — since ZDOTDIR is restored to the user's original value (or unset) at the end of .zshrc, zsh will naturally load the user's .zlogin directly from their real ZDOTDIR. The wrapper is effectively unreachable in the normal flow.

Good call documenting it explicitly in the table. The fallback remains useful in case an edge case or future zsh behavior change causes the wrapper to be invoked, and the ${_CMUX_ORIG_ZDOTDIR-$HOME} fallback ensures it won't break catastrophically even though the variable is already cleaned up.

Comment on lines +28 to +30
builtin typeset _cmux_file="${_CMUX_ORIG_ZDOTDIR}/.zshenv"
[[ ! -r "$_cmux_file" ]] || builtin source -- "$_cmux_file"
builtin unset _cmux_file

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2 Inconsistent default for _CMUX_ORIG_ZDOTDIR

Unlike the wrappers in .zprofile, .zshrc, and .zlogin which all use ${_CMUX_ORIG_ZDOTDIR-$HOME}, this line uses ${_CMUX_ORIG_ZDOTDIR} without a fallback. It is safe here because _CMUX_ORIG_ZDOTDIR is always set in the block immediately above, but for consistency and defensive robustness (e.g. if this file were somehow sourced out-of-order), adding the same default would be cleaner:

Suggested change
builtin typeset _cmux_file="${_CMUX_ORIG_ZDOTDIR}/.zshenv"
[[ ! -r "$_cmux_file" ]] || builtin source -- "$_cmux_file"
builtin unset _cmux_file
builtin typeset _cmux_file="${_CMUX_ORIG_ZDOTDIR-$HOME}/.zshenv"

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Comment on lines +17 to +19
if [[ "$HISTFILE" == "${ZDOTDIR}"/* ]]; then
HISTFILE="${_CMUX_ORIG_ZDOTDIR-$HOME}/.zsh_history"
fi

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2 HISTFILE check uses glob pattern matching

[[ "$HISTFILE" == "${ZDOTDIR}"/* ]] — in zsh [[...]], the right-hand side of == is a pattern. The trailing * is treated as a glob wildcard, so this correctly matches any path whose prefix is ${ZDOTDIR}/. This is fine in practice, but worth being explicit about the intent. If ZDOTDIR ever contained glob meta-characters (e.g. [, (), the match could behave unexpectedly. Using a prefix-string comparison would be more robust:

Suggested change
if [[ "$HISTFILE" == "${ZDOTDIR}"/* ]]; then
HISTFILE="${_CMUX_ORIG_ZDOTDIR-$HOME}/.zsh_history"
fi
if [[ "${HISTFILE}" == "${ZDOTDIR}/"* ]]; then

(No functional change — just clarifying the intended prefix match with the slash inside the literal part.)

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@Resources/shell-integration/.zshenv`:
- Around line 16-30: The wrapper currently sources the user's file while ZDOTDIR
still points to the wrapper; before sourcing set ZDOTDIR to the saved original
and after sourcing capture any user-modified ZDOTDIR back into
_CMUX_ORIG_ZDOTDIR so later wrappers honor user overrides. Concretely, in the
.zshenv wrapper save the wrapper's ZDOTDIR to a temp variable, export
ZDOTDIR="$_CMUX_ORIG_ZDOTDIR" (or restore from
GHOSTTY_ZSH_ZDOTDIR/CMUX_ZSH_ZDOTDIR logic) before sourcing _cmux_file, then
after sourcing set _CMUX_ORIG_ZDOTDIR="$ZDOTDIR" and restore the wrapper ZDOTDIR
from the temp var and cleanup temp vars; apply the same pattern to the
.zprofile, .zshrc, and .zlogin wrappers referencing _CMUX_ORIG_ZDOTDIR and
_cmux_file to locate the source points.

In `@Resources/shell-integration/.zshrc`:
- Around line 10-19: The wrapper must capture the post-user-init ZDOTDIR and use
it when sourcing user files and setting HISTFILE: in .zshenv (after sourcing the
user's .zshenv) export a new variable _CMUX_EFFECTIVE_ZDOTDIR set to
"${ZDOTDIR:-${_CMUX_ORIG_ZDOTDIR:-$HOME}}", then update .zshrc (and mirror the
same changes in .zprofile and .zlogin) to replace uses of _CMUX_ORIG_ZDOTDIR
with _CMUX_EFFECTIVE_ZDOTDIR for sourcing the user's .zshrc and for computing
HISTFILE so the wrapper respects any ZDOTDIR the user's .zshenv set.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: cc4bceab-e4e1-4ea7-a7ce-cfc5d4c556d5

📥 Commits

Reviewing files that changed from the base of the PR and between 37b5e54 and 372d640.

📒 Files selected for processing (4)
  • Resources/shell-integration/.zlogin
  • Resources/shell-integration/.zprofile
  • Resources/shell-integration/.zshenv
  • Resources/shell-integration/.zshrc

Comment on lines +16 to +30
# Save the user's original ZDOTDIR so wrappers can find user files.
if [[ -n "${GHOSTTY_ZSH_ZDOTDIR+X}" ]]; then
builtin export ZDOTDIR="$GHOSTTY_ZSH_ZDOTDIR"
builtin export _CMUX_ORIG_ZDOTDIR="$GHOSTTY_ZSH_ZDOTDIR"
builtin unset GHOSTTY_ZSH_ZDOTDIR
elif [[ -n "${CMUX_ZSH_ZDOTDIR+X}" ]]; then
builtin export ZDOTDIR="$CMUX_ZSH_ZDOTDIR"
builtin export _CMUX_ORIG_ZDOTDIR="$CMUX_ZSH_ZDOTDIR"
builtin unset CMUX_ZSH_ZDOTDIR
else
builtin unset ZDOTDIR
builtin export _CMUX_ORIG_ZDOTDIR="${HOME}"
fi

{
# zsh treats unset ZDOTDIR as if it were HOME. We do the same.
builtin typeset _cmux_file="${ZDOTDIR-$HOME}/.zshenv"
[[ ! -r "$_cmux_file" ]] || builtin source -- "$_cmux_file"
} always {
if [[ -o interactive ]]; then
# We overwrote GhosttyKit's injected ZDOTDIR, so manually load Ghostty's
# zsh integration if available.
#
# We can't rely on GHOSTTY_ZSH_ZDOTDIR here because Ghostty's own zsh
# bootstrap unsets it before chaining into this cmux wrapper.
if [[ "${CMUX_LOAD_GHOSTTY_ZSH_INTEGRATION:-0}" == "1" ]]; then
if [[ -n "${CMUX_SHELL_INTEGRATION_DIR:-}" ]]; then
builtin typeset _cmux_ghostty="$CMUX_SHELL_INTEGRATION_DIR/ghostty-integration.zsh"
fi
if [[ ! -r "${_cmux_ghostty:-}" && -n "${GHOSTTY_RESOURCES_DIR:-}" ]]; then
builtin typeset _cmux_ghostty="$GHOSTTY_RESOURCES_DIR/shell-integration/zsh/ghostty-integration"
fi
[[ -r "$_cmux_ghostty" ]] && builtin source -- "$_cmux_ghostty"
fi

# Load cmux integration (unless disabled)
if [[ "${CMUX_SHELL_INTEGRATION:-1}" != "0" && -n "${CMUX_SHELL_INTEGRATION_DIR:-}" ]]; then
builtin typeset _cmux_integ="$CMUX_SHELL_INTEGRATION_DIR/cmux-zsh-integration.zsh"
[[ -r "$_cmux_integ" ]] && builtin source -- "$_cmux_integ"
fi
fi

builtin unset _cmux_file _cmux_ghostty _cmux_integ
}
# Source the user's .zshenv (runs for all shells, interactive or not).
builtin typeset _cmux_file="${_CMUX_ORIG_ZDOTDIR}/.zshenv"
[[ ! -r "$_cmux_file" ]] || builtin source -- "$_cmux_file"
builtin unset _cmux_file

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== shell wrappers ==="
for f in \
  Resources/shell-integration/.zshenv \
  Resources/shell-integration/.zprofile \
  Resources/shell-integration/.zshrc \
  Resources/shell-integration/.zlogin
do
  echo "--- $f ---"
  sed -n '1,140p' "$f"
  echo
done

echo "=== ZDOTDIR-related tests ==="
if [ -d tests ]; then
  rg -n -C3 'export ZDOTDIR=|user startup files see original ZDOTDIR|expected \.zshrc from alt ZDOTDIR|CMUX_ZSH_ZDOTDIR' tests || true
else
  echo "tests/ not present"
fi

Repository: manaflow-ai/cmux

Length of output: 7983


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== test_shell_zdotdir_wrapper.py (full) ==="
if [ -f tests/test_shell_zdotdir_wrapper.py ]; then
  cat tests/test_shell_zdotdir_wrapper.py
fi

echo ""
echo "=== test_shell_zdotdir_user_override.py (full) ==="
if [ -f tests/test_shell_zdotdir_user_override.py ]; then
  cat tests/test_shell_zdotdir_user_override.py
fi

Repository: manaflow-ai/cmux

Length of output: 6042


Restore the user's ZDOTDIR before sourcing startup files so wrappers honor user overrides.

The current .zshenv sources the user's real startup file while ZDOTDIR still points at the wrapper directory. This breaks shell integration semantics in two ways:

  1. User code sees wrong ZDOTDIR — The test test_shell_zdotdir_wrapper.py expects user startup files to see the original user ZDOTDIR, not the wrapper directory.

  2. User ZDOTDIR overrides are ignored — If a user's .zshenv exports ZDOTDIR to a different path (common in dotfiles-managed setups), the test test_shell_zdotdir_user_override.py expects later startup files (.zshrc, .zlogin) to be sourced from the updated path. Currently, .zprofile and .zshrc wrappers source from the frozen _CMUX_ORIG_ZDOTDIR, ignoring the user's override, which breaks plugin loading and diverges from Ghostty behavior.

Apply this pattern to all wrapper files:

  1. Before sourcing the user's file: save wrapper ZDOTDIR, then unset or restore the user's ZDOTDIR.
  2. After sourcing: capture the potentially-modified $ZDOTDIR for use by later wrappers, then re-wrap.

The same fix applies to .zprofile, .zshrc, and .zlogin wrappers.

Minimal example for .zshenv
+# Keep the wrapper path so later stages still re-enter these wrappers.
+builtin export _CMUX_WRAPPER_ZDOTDIR="${ZDOTDIR}"
+
 # Source the user's .zshenv (runs for all shells, interactive or not).
 builtin typeset _cmux_file="${_CMUX_ORIG_ZDOTDIR}/.zshenv"
-[[ ! -r "$_cmux_file" ]] || builtin source -- "$_cmux_file"
+if [[ -r "$_cmux_file" ]]; then
+    if [[ "${_CMUX_ORIG_ZDOTDIR}" == "${HOME}" ]]; then
+        builtin unset ZDOTDIR
+    else
+        builtin export ZDOTDIR="${_CMUX_ORIG_ZDOTDIR}"
+    fi
+    builtin source -- "$_cmux_file"
+    builtin export _CMUX_EFFECTIVE_ZDOTDIR="${ZDOTDIR:-$HOME}"
+    builtin export ZDOTDIR="${_CMUX_WRAPPER_ZDOTDIR}"
+else
+    builtin export _CMUX_EFFECTIVE_ZDOTDIR="${_CMUX_ORIG_ZDOTDIR}"
+fi
 builtin unset _cmux_file
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
# Save the user's original ZDOTDIR so wrappers can find user files.
if [[ -n "${GHOSTTY_ZSH_ZDOTDIR+X}" ]]; then
builtin export ZDOTDIR="$GHOSTTY_ZSH_ZDOTDIR"
builtin export _CMUX_ORIG_ZDOTDIR="$GHOSTTY_ZSH_ZDOTDIR"
builtin unset GHOSTTY_ZSH_ZDOTDIR
elif [[ -n "${CMUX_ZSH_ZDOTDIR+X}" ]]; then
builtin export ZDOTDIR="$CMUX_ZSH_ZDOTDIR"
builtin export _CMUX_ORIG_ZDOTDIR="$CMUX_ZSH_ZDOTDIR"
builtin unset CMUX_ZSH_ZDOTDIR
else
builtin unset ZDOTDIR
builtin export _CMUX_ORIG_ZDOTDIR="${HOME}"
fi
{
# zsh treats unset ZDOTDIR as if it were HOME. We do the same.
builtin typeset _cmux_file="${ZDOTDIR-$HOME}/.zshenv"
[[ ! -r "$_cmux_file" ]] || builtin source -- "$_cmux_file"
} always {
if [[ -o interactive ]]; then
# We overwrote GhosttyKit's injected ZDOTDIR, so manually load Ghostty's
# zsh integration if available.
#
# We can't rely on GHOSTTY_ZSH_ZDOTDIR here because Ghostty's own zsh
# bootstrap unsets it before chaining into this cmux wrapper.
if [[ "${CMUX_LOAD_GHOSTTY_ZSH_INTEGRATION:-0}" == "1" ]]; then
if [[ -n "${CMUX_SHELL_INTEGRATION_DIR:-}" ]]; then
builtin typeset _cmux_ghostty="$CMUX_SHELL_INTEGRATION_DIR/ghostty-integration.zsh"
fi
if [[ ! -r "${_cmux_ghostty:-}" && -n "${GHOSTTY_RESOURCES_DIR:-}" ]]; then
builtin typeset _cmux_ghostty="$GHOSTTY_RESOURCES_DIR/shell-integration/zsh/ghostty-integration"
fi
[[ -r "$_cmux_ghostty" ]] && builtin source -- "$_cmux_ghostty"
fi
# Load cmux integration (unless disabled)
if [[ "${CMUX_SHELL_INTEGRATION:-1}" != "0" && -n "${CMUX_SHELL_INTEGRATION_DIR:-}" ]]; then
builtin typeset _cmux_integ="$CMUX_SHELL_INTEGRATION_DIR/cmux-zsh-integration.zsh"
[[ -r "$_cmux_integ" ]] && builtin source -- "$_cmux_integ"
fi
fi
builtin unset _cmux_file _cmux_ghostty _cmux_integ
}
# Source the user's .zshenv (runs for all shells, interactive or not).
builtin typeset _cmux_file="${_CMUX_ORIG_ZDOTDIR}/.zshenv"
[[ ! -r "$_cmux_file" ]] || builtin source -- "$_cmux_file"
builtin unset _cmux_file
# Save the user's original ZDOTDIR so wrappers can find user files.
if [[ -n "${GHOSTTY_ZSH_ZDOTDIR+X}" ]]; then
builtin export _CMUX_ORIG_ZDOTDIR="$GHOSTTY_ZSH_ZDOTDIR"
builtin unset GHOSTTY_ZSH_ZDOTDIR
elif [[ -n "${CMUX_ZSH_ZDOTDIR+X}" ]]; then
builtin export _CMUX_ORIG_ZDOTDIR="$CMUX_ZSH_ZDOTDIR"
builtin unset CMUX_ZSH_ZDOTDIR
else
builtin export _CMUX_ORIG_ZDOTDIR="${HOME}"
fi
# Keep the wrapper path so later stages still re-enter these wrappers.
builtin export _CMUX_WRAPPER_ZDOTDIR="${ZDOTDIR}"
# Source the user's .zshenv (runs for all shells, interactive or not).
builtin typeset _cmux_file="${_CMUX_ORIG_ZDOTDIR}/.zshenv"
if [[ -r "$_cmux_file" ]]; then
if [[ "${_CMUX_ORIG_ZDOTDIR}" == "${HOME}" ]]; then
builtin unset ZDOTDIR
else
builtin export ZDOTDIR="${_CMUX_ORIG_ZDOTDIR}"
fi
builtin source -- "$_cmux_file"
builtin export _CMUX_EFFECTIVE_ZDOTDIR="${ZDOTDIR:-$HOME}"
builtin export ZDOTDIR="${_CMUX_WRAPPER_ZDOTDIR}"
else
builtin export _CMUX_EFFECTIVE_ZDOTDIR="${_CMUX_ORIG_ZDOTDIR}"
fi
builtin unset _cmux_file
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Resources/shell-integration/.zshenv` around lines 16 - 30, The wrapper
currently sources the user's file while ZDOTDIR still points to the wrapper;
before sourcing set ZDOTDIR to the saved original and after sourcing capture any
user-modified ZDOTDIR back into _CMUX_ORIG_ZDOTDIR so later wrappers honor user
overrides. Concretely, in the .zshenv wrapper save the wrapper's ZDOTDIR to a
temp variable, export ZDOTDIR="$_CMUX_ORIG_ZDOTDIR" (or restore from
GHOSTTY_ZSH_ZDOTDIR/CMUX_ZSH_ZDOTDIR logic) before sourcing _cmux_file, then
after sourcing set _CMUX_ORIG_ZDOTDIR="$ZDOTDIR" and restore the wrapper ZDOTDIR
from the temp var and cleanup temp vars; apply the same pattern to the
.zprofile, .zshrc, and .zlogin wrappers referencing _CMUX_ORIG_ZDOTDIR and
_cmux_file to locate the source points.

Comment on lines +10 to +19
builtin typeset _cmux_file="${_CMUX_ORIG_ZDOTDIR-$HOME}/.zshrc"
[[ ! -r "$_cmux_file" ]] || builtin source -- "$_cmux_file"
builtin unset _cmux_file

# Fix HISTFILE: /etc/zshrc sets HISTFILE based on ZDOTDIR which currently
# points to our integration dir. Only fix if it still points there;
# if the user's .zshrc set a custom HISTFILE, respect it.
if [[ "$HISTFILE" == "${ZDOTDIR}"/* ]]; then
HISTFILE="${_CMUX_ORIG_ZDOTDIR-$HOME}/.zsh_history"
fi

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

# First, let's find the shell integration files
find . -path "*/Resources/shell-integration/*.zsh*" -type f | head -20

Repository: manaflow-ai/cmux

Length of output: 189


🏁 Script executed:

# Check the current state of .zshrc
cat -n Resources/shell-integration/.zshrc | head -50

Repository: manaflow-ai/cmux

Length of output: 2234


🏁 Script executed:

# Check .zshenv and .zprofile for variable initialization
cat -n Resources/shell-integration/.zshenv | head -50

Repository: manaflow-ai/cmux

Length of output: 1557


🏁 Script executed:

# Look for the test file mentioned
find . -name "test_shell_zdotdir_user_override.py" -type f

Repository: manaflow-ai/cmux

Length of output: 103


🏁 Script executed:

# Now let's examine the test file to understand the expected behavior
cat -n tests/test_shell_zdotdir_user_override.py

Repository: manaflow-ai/cmux

Length of output: 4116


🏁 Script executed:

# Also check .zprofile for completeness
cat -n Resources/shell-integration/.zprofile | head -50

Repository: manaflow-ai/cmux

Length of output: 382


🏁 Script executed:

# Let's verify if _CMUX_EFFECTIVE_ZDOTDIR is currently being set anywhere
rg "_CMUX_EFFECTIVE_ZDOTDIR" Resources/shell-integration/

Repository: manaflow-ai/cmux

Length of output: 42


🏁 Script executed:

# Let's also check what happens in the zsh startup flow by examining cmux-zsh-integration.zsh
cat -n Resources/shell-integration/cmux-zsh-integration.zsh | head -30

Repository: manaflow-ai/cmux

Length of output: 1571


🏁 Script executed:

# Let's trace through the zsh startup sequence more carefully
# Check if there are more .zprofile details or if it's modified anywhere
rg "ZDOTDIR" Resources/shell-integration/ -A 2 -B 2

Repository: manaflow-ai/cmux

Length of output: 42


🏁 Script executed:

# Let's run the test to see if it currently passes or fails
python3 tests/test_shell_zdotdir_user_override.py

Repository: manaflow-ai/cmux

Length of output: 869


🏁 Script executed:

# Let's check if there's any attempt to capture post-user-init ZDOTDIR in .zshenv
cat -n Resources/shell-integration/.zshenv

Repository: manaflow-ai/cmux

Length of output: 1557


🏁 Script executed:

# Also check .zlogin to see if it has similar issues
cat -n Resources/shell-integration/.zlogin 2>/dev/null || echo "No .zlogin file"

Repository: manaflow-ai/cmux

Length of output: 376


Capture post-user-init ZDOTDIR and use it in .zshrc.

After the user's .zshenv runs (line 30), it may redirect ZDOTDIR to a custom location (e.g., ~/dotfiles). The wrapper .zshrc currently uses _CMUX_ORIG_ZDOTDIR to source files, causing it to ignore the user's updated directory. This breaks the test expectation that .zshrc and HISTFILE are sourced from the post-user-init ZDOTDIR.

To fix this:

  1. At the end of .zshenv (after sourcing the user's .zshenv), capture the current ZDOTDIR as _CMUX_EFFECTIVE_ZDOTDIR
  2. In .zshrc, use _CMUX_EFFECTIVE_ZDOTDIR instead of _CMUX_ORIG_ZDOTDIR for lines 10, 18, and 39-42
  3. Do the same for .zprofile and .zlogin
Expected changes to .zshenv

After line 29 (after sourcing the user's .zshenv), add:

builtin export _CMUX_EFFECTIVE_ZDOTDIR="${ZDOTDIR:-${_CMUX_ORIG_ZDOTDIR:-$HOME}}"
Expected changes to .zshrc
-builtin typeset _cmux_file="${_CMUX_ORIG_ZDOTDIR-$HOME}/.zshrc"
+builtin typeset _cmux_file="${_CMUX_EFFECTIVE_ZDOTDIR-${_CMUX_ORIG_ZDOTDIR:-$HOME}}/.zshrc"
 [[ ! -r "$_cmux_file" ]] || builtin source -- "$_cmux_file"
 builtin unset _cmux_file
 ...
-    HISTFILE="${_CMUX_ORIG_ZDOTDIR-$HOME}/.zsh_history"
+    HISTFILE="${_CMUX_EFFECTIVE_ZDOTDIR-${_CMUX_ORIG_ZDOTDIR:-$HOME}}/.zsh_history"
 ...
-if [[ "${_CMUX_ORIG_ZDOTDIR}" == "${HOME}" ]]; then
+if [[ "${_CMUX_EFFECTIVE_ZDOTDIR}" == "${HOME}" ]]; then
     builtin unset ZDOTDIR
 else
-    builtin export ZDOTDIR="${_CMUX_ORIG_ZDOTDIR}"
+    builtin export ZDOTDIR="${_CMUX_EFFECTIVE_ZDOTDIR}"
 fi
-builtin unset _CMUX_ORIG_ZDOTDIR _cmux_ghostty _cmux_integ
+builtin unset _CMUX_ORIG_ZDOTDIR _CMUX_EFFECTIVE_ZDOTDIR _cmux_ghostty _cmux_integ

Also applies to: .zprofile and .zlogin

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Resources/shell-integration/.zshrc` around lines 10 - 19, The wrapper must
capture the post-user-init ZDOTDIR and use it when sourcing user files and
setting HISTFILE: in .zshenv (after sourcing the user's .zshenv) export a new
variable _CMUX_EFFECTIVE_ZDOTDIR set to
"${ZDOTDIR:-${_CMUX_ORIG_ZDOTDIR:-$HOME}}", then update .zshrc (and mirror the
same changes in .zprofile and .zlogin) to replace uses of _CMUX_ORIG_ZDOTDIR
with _CMUX_EFFECTIVE_ZDOTDIR for sourcing the user's .zshrc and for computing
HISTFILE so the wrapper respects any ZDOTDIR the user's .zshenv set.

@rerun0510
rerun0510 force-pushed the fix/shell-integration-deferred-load branch from 1321a02 to 372d640 Compare March 25, 2026 05:31
Defer integration loading to .zshrc wrapper instead of .zshenv so that
tools like Kiro CLI that reset precmd_functions in .zprofile cannot
clobber cmux's hooks. Keep ZDOTDIR pointing to the integration directory
through the full zsh startup sequence and restore it after loading.
@rerun0510
rerun0510 force-pushed the fix/shell-integration-deferred-load branch from 372d640 to ccf948f Compare March 25, 2026 05:33
@rerun0510

Copy link
Copy Markdown
Contributor Author

@lawrencecchen
This changes the fundamental loading strategy for shell integration (from early load in .zshenv to deferred load in .zshrc). If this direction doesn't align with the project's approach, feel free to close this PR.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

♻️ Duplicate comments (1)
Resources/shell-integration/.zshenv (1)

17-29: ⚠️ Potential issue | 🔴 Critical

Restore the effective ZDOTDIR around the user .zshenv.

On Lines 17-25 and Lines 28-29, _CMUX_ORIG_ZDOTDIR is fixed before the user's .zshenv runs, while ZDOTDIR still points at the integration directory. That makes dotfiles observe the wrong $ZDOTDIR, leaves non-interactive shells with the wrapper value because they never reach .zshrc, and prevents later wrappers from following a user export ZDOTDIR=... inside .zshenv. Restore/unset ZDOTDIR before source, then capture the post-source effective value back into _CMUX_ORIG_ZDOTDIR before re-wrapping.

Expect .zshenv to restore/unset ZDOTDIR around the user source, then later wrappers to use the updated _CMUX_ORIG_ZDOTDIR.

#!/bin/bash
set -euo pipefail

echo "=== shell wrappers ==="
for f in \
  Resources/shell-integration/.zshenv \
  Resources/shell-integration/.zprofile \
  Resources/shell-integration/.zshrc \
  Resources/shell-integration/.zlogin
do
  echo "--- $f ---"
  sed -n '1,180p' "$f"
  echo
done

echo "=== ZDOTDIR tests ==="
for f in \
  tests/test_shell_zdotdir_wrapper.py \
  tests/test_shell_zdotdir_user_override.py
do
  if [ -f "$f" ]; then
    echo "--- $f ---"
    sed -n '1,220p' "$f"
    echo
  fi
done
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Resources/shell-integration/.zshenv` around lines 17 - 29, The wrapper sets
_CMUX_ORIG_ZDOTDIR while leaving ZDOTDIR pointing at the integration dir, so
user .zshenv sees the wrong $ZDOTDIR and later exports are ignored; fix by
saving the current wrapper vars (GHOSTTY_ZSH_ZDOTDIR/CMUX_ZSH_ZDOTDIR) into
_CMUX_ORIG_ZDOTDIR as you do, then unset or restore ZDOTDIR (unset ZDOTDIR or
set it to the user's original value) immediately before sourcing _cmux_file, and
after sourcing capture the effective ZDOTDIR back into _CMUX_ORIG_ZDOTDIR (e.g.,
inspect $ZDOTDIR or default to $HOME) and re-export/reset any wrapper variables
so later wrappers see the updated value; update the logic around variables
_CMUX_ORIG_ZDOTDIR, GHOSTTY_ZSH_ZDOTDIR, CMUX_ZSH_ZDOTDIR and _cmux_file
accordingly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@Resources/shell-integration/.zshenv`:
- Around line 17-29: The wrapper sets _CMUX_ORIG_ZDOTDIR while leaving ZDOTDIR
pointing at the integration dir, so user .zshenv sees the wrong $ZDOTDIR and
later exports are ignored; fix by saving the current wrapper vars
(GHOSTTY_ZSH_ZDOTDIR/CMUX_ZSH_ZDOTDIR) into _CMUX_ORIG_ZDOTDIR as you do, then
unset or restore ZDOTDIR (unset ZDOTDIR or set it to the user's original value)
immediately before sourcing _cmux_file, and after sourcing capture the effective
ZDOTDIR back into _CMUX_ORIG_ZDOTDIR (e.g., inspect $ZDOTDIR or default to
$HOME) and re-export/reset any wrapper variables so later wrappers see the
updated value; update the logic around variables _CMUX_ORIG_ZDOTDIR,
GHOSTTY_ZSH_ZDOTDIR, CMUX_ZSH_ZDOTDIR and _cmux_file accordingly.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 65d678de-fc75-44ac-9daa-fb6250060139

📥 Commits

Reviewing files that changed from the base of the PR and between 372d640 and ccf948f.

📒 Files selected for processing (4)
  • Resources/shell-integration/.zlogin
  • Resources/shell-integration/.zprofile
  • Resources/shell-integration/.zshenv
  • Resources/shell-integration/.zshrc
✅ Files skipped from review due to trivial changes (1)
  • Resources/shell-integration/.zlogin
🚧 Files skipped from review as they are similar to previous changes (2)
  • Resources/shell-integration/.zprofile
  • Resources/shell-integration/.zshrc

@teamleaderleo teamleaderleo added area: terminal Ghostty surface, rendering, scrollback, escape sequences, fonts S2: major A crash, hang, lost state, broken connection, or a regression on a path people use labels Sep 30, 2026

This branch has not been deployed

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

Labels

area: terminal Ghostty surface, rendering, scrollback, escape sequences, fonts S2: major A crash, hang, lost state, broken connection, or a regression on a path people use

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ZDOTDIR set to nonexistent shell-integration directory breaks ~/.zshrc loading

2 participants