Skip to content

fix(kaos): enrich PATH from the user's login shell at startup#1339

Merged
RealKai42 merged 8 commits into
mainfrom
kaiyi/addis-ababa
Jul 3, 2026
Merged

fix(kaos): enrich PATH from the user's login shell at startup#1339
RealKai42 merged 8 commits into
mainfrom
kaiyi/addis-ababa

Conversation

@RealKai42

Copy link
Copy Markdown
Collaborator

Problem

User report: the Bash tool cannot find locally installed tools like gh.

When kimi-code is launched from a context that skipped the user's shell profile (GUI launchers, non-login parent shells), process.env.PATH misses entries like /opt/homebrew/bin. The Bash tool spawns commands via a non-interactive, non-login shell that inherits process.env directly, so every spawned command inherits the impoverished PATH.

Fix

LocalKaos.create() now probes the user's login shell once and merges the result into process.env.PATH:

  • Runs $SHELL -l -c env with a 5s timeout and extracts its PATH. Using env (rather than echo $PATH) keeps the probe correct across shell dialects — fish would join $PATH with spaces — and taking the last PATH= line filters out profile stdout noise.
  • Union merge: existing entries keep their order and priority; only entries the current PATH lacks are appended.
  • Silent degradation: missing/blank $SHELL, spawn failure, timeout, or no PATH in the output leave PATH untouched.
  • Memoised like detectEnvironmentFromNode(), and runs concurrently with it, so repeated create() calls never re-spawn the shell.
  • Skipped on Windows: the problem is specific to POSIX login-shell profiles.

Testing

  • New packages/kaos/test/login-shell-path.test.ts: 12 unit tests over the pure probe/merge functions (injected deps, run on every platform) plus an end-to-end test that points $SHELL at a stub shell and asserts LocalKaos.create() appends the missing entry.
  • Followed a failing-test-first flow: the end-to-end test was red before the fix and is green after.
  • Full kaos suite (287 tests), typecheck, and lint pass. The full repo suite passes except 6 pre-existing test/cli/update/preflight.test.ts rollout-gating failures that reproduce identically on main without this change.

RealKai42 added 4 commits July 3, 2026 11:53
When kimi-code is launched from a context that skipped the user's shell
profile (GUI launchers, non-login parent shells), process.env.PATH misses
entries like /opt/homebrew/bin, so commands spawned by the Bash tool
cannot find user-installed tools such as gh.

LocalKaos.create() now probes the user's login shell once
($SHELL -l -c env, 5s timeout, memoised) and appends the missing PATH
entries to process.env.PATH. Existing entries keep their order and
priority; probe failures silently leave PATH untouched. Windows is
skipped: the problem is specific to POSIX login-shell profiles.
@changeset-bot

changeset-bot Bot commented Jul 3, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 4df7123

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@moonshot-ai/kimi-code Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@pkg-pr-new

pkg-pr-new Bot commented Jul 3, 2026

Copy link
Copy Markdown
pnpm dlx https://pkg.pr.new/@moonshot-ai/kimi-code@4df7123
npx https://pkg.pr.new/@moonshot-ai/kimi-code@4df7123

commit: 4df7123

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 123d6f9f4d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/kaos/src/login-shell-path.ts Outdated
Comment on lines +40 to +41
const shell = deps.env['SHELL']?.trim();
if (shell === undefined || shell.length === 0) return undefined;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Handle blank SHELL when enriching PATH

In launchd/daemon launches, $SHELL can be unset or blank (the repo already handles that case in packages/agent-core/src/services/terminal/terminalService.ts:267-270). This early return means those GUI/service startup paths never probe a login shell, so PATH remains the launchd/system default and the Bash tool still won't find user-installed tools such as Homebrew gh; please fall back to the OS account shell (for example os.userInfo().shell) before giving up.

Useful? React with 👍 / 👎.

launchd/daemon launches can leave $SHELL unset or blank — the very
contexts whose PATH is impoverished — so the login-shell PATH probe
would give up exactly where it matters most. Resolve the shell from the
OS user database (os.userInfo().shell) before giving up; lookups that
throw (uid without a database entry) or yield nologin shells degrade
silently as before.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: fcf381cedd

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/kaos/src/login-shell-path.ts Outdated
currentPath: string | undefined,
loginShellPath: string,
): string {
const merged = (currentPath ?? '').split(':').filter((entry) => entry.length > 0);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Preserve empty PATH components

When the existing PATH contains an empty component such as :/usr/bin, /usr/bin:, or ::, POSIX command lookup treats that component as the current directory. This filter removes those entries before writing the merged value back to process.env.PATH, so the first LocalKaos.create() silently changes lookup semantics for all later Bash/exec calls instead of only appending login-shell entries; users who intentionally rely on the current directory in PATH lose it. Please preserve empty components from the current PATH while appending only the missing login-shell entries.

Useful? React with 👍 / 👎.

POSIX command lookup treats an empty PATH component (leading colon,
trailing colon, or double colon) as the current directory. The merge
previously filtered those out of the current PATH and rewrote the value
even when nothing was appended, silently dropping cwd lookup for users
who rely on it.

Keep the current PATH string verbatim as the prefix, append only the
missing login-shell entries, and skip the env write entirely when the
login shell contributes nothing — an unset PATH stays unset, a set PATH
is never rewritten. Empty login-shell components are still never
imported.
@RealKai42

Copy link
Copy Markdown
Collaborator Author

@codex

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b1358fbfab

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/kaos/src/login-shell-path.ts Outdated
const seen = new Set(current.split(':').filter((entry) => entry.length > 0));
const additions: string[] = [];
for (const entry of loginShellPath.split(':')) {
if (entry.length === 0 || seen.has(entry)) continue;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Skip relative login PATH entries

When the login-shell PATH contains . or another relative component such as bin and the current PATH does not, this merge appends it to the global process.env.PATH. LocalKaos later runs commands from arbitrary workspace directories, so a command name missing from earlier PATH entries can now resolve from the project cwd, importing the same cwd-dependent lookup that the empty-component guard is trying to avoid. Consider skipping ./relative entries here, or only importing absolute login-shell paths.

Useful? React with 👍 / 👎.

A `.` or relative component in the login-shell PATH is cwd-dependent
lookup with another spelling, and LocalKaos runs commands from arbitrary
workspace directories — importing one would let a command name resolve
from an untrusted project cwd. Tighten the merge's skip condition from
"empty" to "not absolute", which subsumes the empty-component check.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b7684c37ce

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/kaos/src/login-shell-path.ts Outdated

// `env` prints the resolved environment in every shell dialect, unlike
// `echo $PATH`, which fish would join with spaces.
const stdout = await deps.execFileText(shell, ['-l', '-c', 'env'], LOGIN_SHELL_ENV_TIMEOUT_MS);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Use an absolute env for the login-shell probe

When Kimi is launched from a workspace with a cwd-dependent PATH component (PATH=:/usr/bin, PATH=.:..., etc.), the new startup probe runs the bare command env inside $SHELL -l -c ..., so the shell resolves env through that PATH before mergeLoginShellPath has a chance to filter relative login entries. That means an executable named env in the project can be run automatically during LocalKaos.create() and can return an arbitrary PATH; use an absolute system env path or another non-PATH lookup for the probe.

Useful? React with 👍 / 👎.

A bare `env` inside `$SHELL -l -c` resolves through the inherited PATH
from the workspace cwd. If that PATH carries a cwd-dependent component
(which the merge deliberately preserves), a repo-planted `env` binary
would run automatically at session startup and could feed the probe an
arbitrary PATH. /usr/bin/env is guaranteed on mainstream POSIX systems
and also bypasses profile function shadowing.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 4df71234c0

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

// shadowing, and /usr/bin/env is guaranteed on every mainstream POSIX
// system (it is the canonical shebang interpreter path).
const stdout = await deps.execFileText(
shell,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Reject non-absolute login shells

When a launcher provides SHELL as a bare name or relative path (for example SHELL=bash) and the inherited PATH contains a cwd-dependent component such as . or an empty entry, this execFile call resolves the shell itself through that untrusted PATH. In a workspace with a checked-in executable named bash, LocalKaos.create() can run it automatically before the /usr/bin/env safeguard applies and then accept its forged PATH; please require an absolute shell path (or fall back to the account shell) before spawning.

Useful? React with 👍 / 👎.

@RealKai42 RealKai42 merged commit 021786f into main Jul 3, 2026
9 checks passed
@RealKai42 RealKai42 deleted the kaiyi/addis-ababa branch July 3, 2026 07:20
@github-actions github-actions Bot mentioned this pull request Jul 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant