Skip to content

fix: resolve Claude CLI not found on Windows - PATH, prompt size, cwd (#1661)#1843

Open
AndyMik90 wants to merge 3 commits intodevelopfrom
fix/1661-claude-code-not-found
Open

fix: resolve Claude CLI not found on Windows - PATH, prompt size, cwd (#1661)#1843
AndyMik90 wants to merge 3 commits intodevelopfrom
fix/1661-claude-code-not-found

Conversation

@AndyMik90
Copy link
Owner

@AndyMik90 AndyMik90 commented Feb 15, 2026

Summary

Fixes three root causes behind "Claude code not found" errors on Windows Kanban tasks (#1661):

  • PATH overwrite: pythonEnv.PATH (containing only pywin32_system32) was spread after the augmented env.PATH (containing npm globals, Homebrew, etc.), overwriting it. Now merges PATH entries instead - prepends python-specific paths while preserving all augmented entries.
  • System prompt size: The SDK passes system_prompt as a --system-prompt CLI argument. Large CLAUDE.md files exceed Windows CreateProcessW's 32,768 char limit, causing ERROR_FILE_NOT_FOUND which the SDK misreports as "Claude Code not found". Now caps CLAUDE.md content on Windows to stay under the limit.
  • Cross-drive cwd: Agent processes were spawned with autoBuildSource (backend dir) as cwd. On Windows cross-drive setups (e.g., backend on C:, project on D:), this caused file access issues. Now uses projectPath as cwd since all script paths are absolute.

Changes

File Change
apps/frontend/src/main/agent/agent-process.ts Merge PATH entries from pythonEnv with augmented PATH instead of overwriting
apps/backend/core/client.py Cap CLAUDE.md content on Windows to prevent command-line length overflow
apps/frontend/src/main/agent/agent-manager.ts Use projectPath as cwd for spec creation, task execution, and QA spawns

Test plan

  • TypeScript compilation passes (no errors)
  • 55 agent tests pass (agent-process, agent-queue, env-utils)
  • 29 CLI tool manager tests pass
  • Python syntax validation passes
  • Pre-commit hooks pass (lint, typecheck, format)
  • Manual test on Windows with cross-drive project setup
  • Manual test with large CLAUDE.md (>15KB) on Windows

Closes #1661

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes

    • Improved Windows compatibility by truncating oversized system-prompt content to avoid command-line length failures and by adding clear truncation notices when content is shortened.
    • Ensured Python subprocesses run from the project directory and now preserve/merge PATH entries so modules and files resolve correctly across platforms.
  • Tests

    • Updated integration tests to expect the new subprocess working-directory behavior.

…e cap, and cwd (#1661)

Three root causes addressed:

1. PATH overwrite: pythonEnv.PATH was overwriting the augmented PATH (with npm
   globals) in spawn env. Now merges PATH entries instead, prepending
   python-specific paths (pywin32_system32) while preserving all augmented entries.

2. System prompt size: On Windows, SDK passes system_prompt as --system-prompt
   CLI arg. Large CLAUDE.md files exceed CreateProcessW's 32,768 char limit,
   causing misleading "Claude Code not found" error. Now caps CLAUDE.md content
   on Windows to stay under the limit.

3. Cross-drive cwd: Agent processes were spawned with autoBuildSource as cwd.
   On Windows with cross-drive setups, this caused file access issues. Now uses
   projectPath as cwd since all script paths are absolute.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @AndyMik90, 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 delivers critical fixes for Windows users encountering "Claude CLI not found" errors. It comprehensively addresses three distinct root causes: incorrect handling of environment variable PATH merging, limitations on command-line argument length for system prompts, and cross-drive current working directory inconsistencies. These changes significantly enhance the robustness and reliability of agent processes on Windows.

Highlights

  • PATH overwrite resolution: Resolved an issue where pythonEnv.PATH would overwrite the augmented env.PATH on Windows, leading to "Claude code not found" errors. The fix now merges PATH entries by prepending Python-specific paths while preserving all augmented entries.
  • System prompt size limit for Windows: Addressed the Windows CreateProcessW 32,768 character limit for CLI arguments. Previously, large CLAUDE.md files could exceed this limit, causing ERROR_FILE_NOT_FOUND. The CLAUDE.md content is now capped on Windows to stay within the limit.
  • Cross-drive current working directory (cwd) fix: Fixed file access issues on Windows cross-drive setups by changing the current working directory (cwd) for spawned agent processes from autoBuildSource to projectPath. This ensures correct file access since all script paths are absolute.
Changelog
  • apps/backend/core/client.py
    • Capped the content of CLAUDE.md on Windows to prevent command-line length overflow when passed as a system prompt argument.
  • apps/frontend/src/main/agent/agent-manager.ts
    • Modified spawnProcess calls to use projectPath as the current working directory for spec creation, task execution, and QA processes.
  • apps/frontend/src/main/agent/agent-process.ts
    • Implemented logic to merge PATH entries from pythonEnv with the augmented PATH from env instead of overwriting, ensuring all necessary paths are preserved.
    • Imported getPathDelimiter from ../platform to correctly handle path separation based on the operating system.
Activity
  • The author, AndyMik90, created this pull request to address issue Agent error: Claude code not found (Kanban doesn't have access to files) #1661, focusing on resolving 'Claude CLI not found' errors on Windows.
  • The pull request includes a detailed summary, changes, and a test plan, indicating thorough preparation by the author.
  • The test plan outlines successful TypeScript compilation, agent tests, CLI tool manager tests, Python syntax validation, and pre-commit hooks, with manual tests for Windows cross-drive and large CLAUDE.md pending.
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.

@github-actions github-actions bot added area/fullstack This is Frontend + Backend bug Something isn't working size/S Small (10-99 lines) labels Feb 15, 2026
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 15, 2026

📝 Walkthrough

Walkthrough

Adds Windows-specific truncation for CLAUDE.md in system prompts, changes subprocess cwd to the project directory, and merges Python PATH entries into spawned Python process environments to avoid Windows cross-drive and PATH override issues.

Changes

Cohort / File(s) Summary
Backend CLAUDE.md handling
apps/backend/core/client.py
Adds WINDOWS_MAX_SYSTEM_PROMPT_CHARS and WINDOWS_TRUNCATION_MESSAGE; truncates CLAUDE.md content when combined system prompt would exceed Windows CLI length limits and logs/report truncation.
Frontend subprocess cwd changes
apps/frontend/src/main/agent/agent-manager.ts, apps/frontend/src/__tests__/integration/subprocess-spawn.test.ts
Update spawnProcess calls to use projectPath as cwd instead of autoBuildSource; tests updated to expect project path as subprocess CWD to avoid cross-drive issues on Windows.
Frontend Python env PATH merge
apps/frontend/src/main/agent/agent-process.ts
Import path delimiter helper and merge Python-specific PATH entries from pythonEnv into the augmented environment PATH (case-insensitive), prepending missing entries and passing merged env to the Python subprocess so PATH is preserved/enhanced on Windows.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested labels

os/windows, 🔄 Checking, stable-roadmap, v2.7.6

Poem

🐰 I nibbled at paths and trimmed a line,
Kept prompts concise so Windows stays fine,
I hopped the cwd to the project's nest,
Wove PATH threads so Claude can do its best,
Hooray — the rabbit's fixed the quest! 🥕

🚥 Pre-merge checks | ✅ 6
✅ Passed checks (6 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title clearly and concisely describes the main fix: resolving Claude CLI not found on Windows by addressing PATH, prompt size, and cwd issues.
Linked Issues check ✅ Passed The PR addresses all three root causes identified in issue #1661: PATH overwrite handling, Windows system prompt size limits, and cross-drive cwd issues.
Out of Scope Changes check ✅ Passed All changes are directly scoped to resolving the three Windows-specific issues identified in #1661; no unrelated modifications detected.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Merge Conflict Detection ✅ Passed ✅ No merge conflicts detected when merging into develop

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

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/1661-claude-code-not-found

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.

Copy link
Contributor

@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 effectively addresses several critical Windows-specific issues that could cause "Claude code not found" errors. The fixes for PATH variable overwriting, command-line length limits, and cross-drive current working directory problems are all well-implemented and clearly explained. I have one suggestion to improve maintainability by replacing a magic number with a constant in apps/backend/core/client.py. Overall, these are excellent changes that will significantly improve the stability of the application on Windows.

Comment on lines 831 to 836
max_claude_md_chars = 24000 - len(base_prompt)
if len(claude_md_content) > max_claude_md_chars > 0:
claude_md_content = (
claude_md_content[:max_claude_md_chars]
+ "\n\n[... CLAUDE.md truncated due to Windows command-line length limit ...]"
)
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

The logic to truncate CLAUDE.md content on Windows is a good fix for the command-line length limit. To improve maintainability and readability, it would be better to define the magic number 24000 and the truncation message as constants.

You could define these at the top of the module:

WINDOWS_MAX_CMD_LINE_CHARS = 24000
TRUNCATION_MESSAGE = "\n\n[... CLAUDE.md truncated due to Windows command-line length limit ...]"

Then use them in the function as suggested.

Suggested change
max_claude_md_chars = 24000 - len(base_prompt)
if len(claude_md_content) > max_claude_md_chars > 0:
claude_md_content = (
claude_md_content[:max_claude_md_chars]
+ "\n\n[... CLAUDE.md truncated due to Windows command-line length limit ...]"
)
max_claude_md_chars = WINDOWS_MAX_CMD_LINE_CHARS - len(base_prompt)
if len(claude_md_content) > max_claude_md_chars > 0:
claude_md_content = (
claude_md_content[:max_claude_md_chars]
+ TRUNCATION_MESSAGE
)

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@apps/backend/core/client.py`:
- Around line 824-841: The current Windows truncation logic for
claude_md_content uses a fixed reserve (max_claude_md_chars = 24000 -
len(base_prompt)), which can still overflow when other ClaudeAgentOptions fields
(MCP servers, tools, settings path, etc.) are large; update the truncation to
(1) compute the reserved budget dynamically by serializing the other CLI
arguments (the fields used to build the command line from ClaudeAgentOptions)
and subtracting their length from the 32768 Windows limit, or alternatively use
a much more conservative cap (e.g., reserve 16000 chars for CLAUDE.md) so the
prompt cannot cause CreateProcessW to exceed 32768, and (2) prevent confusing
duplicate logs by making the "CLAUDE.md: included in system prompt" print
conditional (use an else branch or only print the included message when no
truncation occurred). Reference the truncation logic around is_windows(),
max_claude_md_chars, claude_md_content, and the two print statements.

@AndyMik90 AndyMik90 self-assigned this Feb 15, 2026
@AndyMik90
Copy link
Owner Author

🤖 Auto Claude PR Review

Merge Verdict: 🔴 BLOCKED

🔴 Blocked - 4 CI check(s) failing. Fix CI before merge.

Blocked: 4 CI check(s) failing. Fix CI before merge.

Risk Assessment

Factor Level Notes
Complexity Low Based on lines changed
Security Impact None Based on security findings
Scope Coherence Good Based on structural review

🚨 Blocking Issues (Must Fix)

  • CI Failed: CI Complete
  • CI Failed: test-frontend (macos-latest)
  • CI Failed: test-frontend (ubuntu-latest)
  • CI Failed: test-frontend (windows-latest)

Generated by Auto Claude PR Review


This review identified blockers that must be resolved before merge. Generated by Auto Claude.

- Extract magic number 24000 into WINDOWS_MAX_SYSTEM_PROMPT_CHARS constant
  (set to 20000 for more conservative ~12KB CLI headroom)
- Extract truncation suffix into WINDOWS_TRUNCATION_MESSAGE constant
- Fix double-print when truncation occurs: only print "included in system
  prompt" when CLAUDE.md was NOT truncated (was_truncated flag)
- Fix CI test failures: update subprocess-spawn tests to expect projectPath
  as cwd instead of autoBuildSource (matches the #1661 CWD change)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@apps/backend/core/client.py`:
- Around line 843-848: The truncation appends WINDOWS_TRUNCATION_MESSAGE after
slicing to max_claude_md_chars, which causes the final claude_md_content to
exceed the WINDOWS_MAX_SYSTEM_PROMPT_CHARS budget; adjust the budget calculation
by subtracting len(WINDOWS_TRUNCATION_MESSAGE) as well. Change the logic around
max_claude_md_chars/claude_md_content to compute allowed =
WINDOWS_MAX_SYSTEM_PROMPT_CHARS - len(base_prompt) -
len(WINDOWS_TRUNCATION_MESSAGE), ensure allowed > 0 before slicing, and then set
claude_md_content = claude_md_content[:allowed] + WINDOWS_TRUNCATION_MESSAGE (or
if allowed <= 0, set claude_md_content = WINDOWS_TRUNCATION_MESSAGE or an
appropriate fallback) so the final length always respects the system prompt
limit.

Comment on lines 843 to 848
max_claude_md_chars = WINDOWS_MAX_SYSTEM_PROMPT_CHARS - len(base_prompt)
if len(claude_md_content) > max_claude_md_chars > 0:
claude_md_content = (
claude_md_content[:max_claude_md_chars]
+ WINDOWS_TRUNCATION_MESSAGE
)
Copy link
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Truncation message length not included in the budget calculation.

After truncation, the actual CLAUDE.md content length is max_claude_md_chars + len(WINDOWS_TRUNCATION_MESSAGE) (~70 extra chars). This slightly overshoots the budget. With ~12 KB headroom it's not a practical problem, but for correctness:

🔧 Suggested fix
-                max_claude_md_chars = WINDOWS_MAX_SYSTEM_PROMPT_CHARS - len(base_prompt)
+                max_claude_md_chars = WINDOWS_MAX_SYSTEM_PROMPT_CHARS - len(base_prompt) - len(WINDOWS_TRUNCATION_MESSAGE)
📝 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
max_claude_md_chars = WINDOWS_MAX_SYSTEM_PROMPT_CHARS - len(base_prompt)
if len(claude_md_content) > max_claude_md_chars > 0:
claude_md_content = (
claude_md_content[:max_claude_md_chars]
+ WINDOWS_TRUNCATION_MESSAGE
)
max_claude_md_chars = WINDOWS_MAX_SYSTEM_PROMPT_CHARS - len(base_prompt) - len(WINDOWS_TRUNCATION_MESSAGE)
if len(claude_md_content) > max_claude_md_chars > 0:
claude_md_content = (
claude_md_content[:max_claude_md_chars]
WINDOWS_TRUNCATION_MESSAGE
)
🤖 Prompt for AI Agents
In `@apps/backend/core/client.py` around lines 843 - 848, The truncation appends
WINDOWS_TRUNCATION_MESSAGE after slicing to max_claude_md_chars, which causes
the final claude_md_content to exceed the WINDOWS_MAX_SYSTEM_PROMPT_CHARS
budget; adjust the budget calculation by subtracting
len(WINDOWS_TRUNCATION_MESSAGE) as well. Change the logic around
max_claude_md_chars/claude_md_content to compute allowed =
WINDOWS_MAX_SYSTEM_PROMPT_CHARS - len(base_prompt) -
len(WINDOWS_TRUNCATION_MESSAGE), ensure allowed > 0 before slicing, and then set
claude_md_content = claude_md_content[:allowed] + WINDOWS_TRUNCATION_MESSAGE (or
if allowed <= 0, set claude_md_content = WINDOWS_TRUNCATION_MESSAGE or an
appropriate fallback) so the final length always respects the system prompt
limit.

Copy link
Owner Author

@AndyMik90 AndyMik90 left a comment

Choose a reason for hiding this comment

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

🤖 Auto Claude PR Review

🟠 Follow-up Review: Needs Revision

🟠 Needs revision - 2 blocking issue(s) require fixes.

Resolution Status

  • Resolved: 0 previous findings addressed
  • Unresolved: 0 previous findings remain
  • 🆕 New Issues: 4 new findings in recent changes

Finding Validation

  • 🔍 Dismissed as False Positives: 0 findings were re-investigated and found to be incorrect
  • Confirmed Valid: 3 findings verified as genuine issues
  • 👤 Needs Human Review: 0 findings require manual verification

🚨 Blocking Issues

  • quality: PATH merging selects wrong PATH key on Windows due to casing
  • quality: Duplicate PATH keys with different casings passed to child process on Windows

Verdict

CI status: ✅ All 20 CI checks passing (resolved from previous 4 failures — good progress). However, 2 medium-severity findings (NEW-001, NEW-002) in the new PATH merging code were confirmed valid by the finding-validator. Both relate to Windows PATH casing: getAugmentedEnv() can produce env objects with both Path (original) and PATH (augmented) keys on Windows. The new merge logic at line 689 uses Object.keys().find() which selects the non-augmented Path first (insertion order), and the final spread produces duplicate PATH keys with different values in the child process environment. The fix is straightforward: prefer uppercase PATH key and normalize to a single key before merging, similar to how python-env-manager.ts already handles this at lines 737-738. NEW-003 (low severity, truncation budget ~116 char overshoot) is confirmed valid but practically harmless given ~12KB headroom. CodeRabbit's concern about insufficient headroom (CMT-001) was already addressed by reducing the constant from 24000 to 20000.

Review Process

Agents invoked: new-code-reviewer, comment-analyzer, finding-validator


This is an AI-generated follow-up review using parallel specialist analysis with finding validation.

Findings (4 selected of 4 total)

🟡 [NEW-001] [MEDIUM] PATH merging selects wrong PATH key on Windows due to casing

📁 apps/frontend/src/main/agent/agent-process.ts:689

On Windows, getAugmentedEnv() produces an env object with both 'Path' (original system PATH from process.env spread) and 'PATH' (augmented paths only). The Object.keys(env).find(k => k.toUpperCase() === 'PATH') call returns 'Path' first (insertion order), so the merge logic uses the non-augmented system PATH as its base. This means augmented entries (npm globals, Claude CLI path, tool-specific paths) added by getAugmentedEnv() are discarded from the merged result, potentially causing 'Claude Code not found' on Windows setups where the claude CLI is only reachable via an augmented PATH entry.

Suggested fix:

Prefer the uppercase 'PATH' key since getAugmentedEnv() always writes to it:

const envPathKey = 'PATH' in env ? 'PATH' : (Object.keys(env).find(k => k.toUpperCase() === 'PATH') || 'PATH');

Alternatively, normalize the env object to a single PATH key before merging, similar to what getPythonEnv() already does at lines 737-738 of python-env-manager.ts.

🟡 [NEW-002] [MEDIUM] Duplicate PATH keys with different casings passed to child process on Windows

📁 apps/frontend/src/main/agent/agent-process.ts:711

When envPathKey (e.g., 'Path' from env) and pythonPathKey (e.g., 'PATH' from mergedPythonEnv) differ in casing, the final spread {...env, ...mergedPythonEnv} produces an env object with BOTH 'Path' and 'PATH' keys. mergedPythonEnv's 'PATH' overwrites env's 'PATH' but env's 'Path' persists. On Windows, CreateProcessW treats env vars case-insensitively, so which PATH value the child process actually uses is undefined. getPythonEnv() in python-env-manager.ts (lines 737-738) already handles this correctly by deleting the non-normalized key, but this new merge code does not.

Suggested fix:

After finding envPathKey, normalize to a single PATH key by deleting the stale variant from env before merging:

if (envPathKey !== 'PATH' && envPathKey in env) {
  env['PATH'] = env[envPathKey];
  delete env[envPathKey];
}

This follows the same pattern used in python-env-manager.ts lines 737-738.

🔵 [NEW-003] [LOW] Truncation budget does not account for appended overhead (~116 chars)

📁 apps/backend/core/client.py:843

The budget max_claude_md_chars = WINDOWS_MAX_SYSTEM_PROMPT_CHARS - len(base_prompt) does not subtract the WINDOWS_TRUNCATION_MESSAGE length (~72 chars) or the header template '\n\n# Project Instructions (from CLAUDE.md)\n\n' (~44 chars). The final system prompt overshoots the 20,000-char target by ~116 characters. With ~12KB headroom to the 32,768 Windows CreateProcessW limit, this is practically inconsequential, but the budget calculation is subtly incorrect.

Suggested fix:

Subtract the overhead from the budget:

overhead = len(WINDOWS_TRUNCATION_MESSAGE) + len('\n\n# Project Instructions (from CLAUDE.md)\n\n')
max_claude_md_chars = WINDOWS_MAX_SYSTEM_PROMPT_CHARS - len(base_prompt) - overhead

🔵 [CMT-001] [LOW] [FROM COMMENTS] CodeRabbit concern about insufficient CLI overhead reserve - already addressed

📁 apps/backend/core/client.py:39

CodeRabbit flagged that the original 8KB reserve (when constant was 24000) may be insufficient for complex MCP configurations. This was already addressed in commit d646c84 by reducing the constant from 24000 to 20000, increasing headroom from ~8KB to ~12KB. No further action needed.


This review was generated by Auto Claude.

- Normalize env objects to a single uppercase 'PATH' key before merging
  to prevent duplicate PATH keys on Windows where process.env has 'Path'
  and getAugmentedEnv() writes 'PATH'. Without this, Object.keys().find()
  returns 'Path' first (insertion order), discarding augmented entries,
  and the final spread produces both 'Path' and 'PATH' keys.
  Follows the same pattern used in python-env-manager.ts. (#1661)

- Subtract WINDOWS_TRUNCATION_MESSAGE length from the truncation budget
  so the final system prompt stays within WINDOWS_MAX_SYSTEM_PROMPT_CHARS.

Addresses PR #1843 review findings NEW-001, NEW-002, NEW-003.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@github-actions github-actions bot added size/M Medium (100-499 lines) and removed size/S Small (10-99 lines) labels Feb 16, 2026
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In `@apps/backend/core/client.py`:
- Around line 836-859: The current Windows truncation logic fails when
max_claude_md_chars <= 0 and ends up appending the full claude_md_content;
update the block around is_windows()/max_claude_md_chars so that if
max_claude_md_chars <= 0 you do not append CLAUDE.md at all (set was_truncated =
True), print a clear message (e.g., "CLAUDE.md: omitted (no budget under Windows
command-line limit)"), and only append claude_md_content when
max_claude_md_chars > 0 (truncating when necessary with
WINDOWS_TRUNCATION_MESSAGE); reference is_windows,
WINDOWS_MAX_SYSTEM_PROMPT_CHARS, base_prompt, WINDOWS_TRUNCATION_MESSAGE,
claude_md_content, and was_truncated to locate where to change the logic and
messages.

In `@apps/frontend/src/main/agent/agent-process.ts`:
- Around line 726-733: The spawn call currently spreads env then mergedPythonEnv
so mergedPythonEnv unconditionally overrides keys from env (including PATH which
you purposely merged earlier), and setupProcessEnvironment() still injects
duplicate Python vars; remove the redundant PYTHON-specific assignments (e.g.,
PYTHONUNBUFFERED, PYTHONIOENCODING, PYTHONUTF8) from setupProcessEnvironment()
so getPythonEnv()/getMergedPythonEnv (the code producing mergedPythonEnv) is the
canonical source, or alternatively change the spawn merge to explicitly merge
Python keys the same way PATH is merged; also update the inline comment near the
spawn (where env, mergedPythonEnv, oauthModeClearVars, apiProfileEnv are
combined) to clearly state that mergedPythonEnv has final precedence for
Python-related vars and PATH merging is preserved.

Comment on lines +836 to +859
# On Windows, the SDK passes system_prompt as a --system-prompt CLI argument.
# Windows CreateProcessW has a 32,768 character limit for the entire command line.
# When CLAUDE.md is very large, the command can exceed this limit, causing Windows
# to return ERROR_FILE_NOT_FOUND which the SDK misreports as "Claude Code not found".
# Cap CLAUDE.md content to keep total command line under the limit. (#1661)
was_truncated = False
if is_windows():
max_claude_md_chars = (
WINDOWS_MAX_SYSTEM_PROMPT_CHARS
- len(base_prompt)
- len(WINDOWS_TRUNCATION_MESSAGE)
)
if len(claude_md_content) > max_claude_md_chars > 0:
claude_md_content = (
claude_md_content[:max_claude_md_chars]
+ WINDOWS_TRUNCATION_MESSAGE
)
print(
" - CLAUDE.md: truncated (exceeded Windows command-line limit)"
)
was_truncated = True
base_prompt = f"{base_prompt}\n\n# Project Instructions (from CLAUDE.md)\n\n{claude_md_content}"
print(" - CLAUDE.md: included in system prompt")
if not was_truncated:
print(" - CLAUDE.md: included in system prompt")
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Edge case: when max_claude_md_chars <= 0, full CLAUDE.md is included untruncated.

If base_prompt + WINDOWS_TRUNCATION_MESSAGE already exceeds WINDOWS_MAX_SYSTEM_PROMPT_CHARS, the > 0 guard skips truncation and the entire CLAUDE.md is appended — which will definitely exceed the Windows limit. While base_prompt is currently short (~400 chars), this is a latent bug if the prompt grows.

Proposed fix: omit CLAUDE.md when budget is exhausted
             if is_windows():
                 max_claude_md_chars = (
                     WINDOWS_MAX_SYSTEM_PROMPT_CHARS
                     - len(base_prompt)
                     - len(WINDOWS_TRUNCATION_MESSAGE)
                 )
-                if len(claude_md_content) > max_claude_md_chars > 0:
+                if max_claude_md_chars <= 0:
+                    claude_md_content = ""
+                    print(
+                        "   - CLAUDE.md: omitted (base prompt already near Windows limit)"
+                    )
+                    was_truncated = True
+                elif len(claude_md_content) > max_claude_md_chars:
                     claude_md_content = (
                         claude_md_content[:max_claude_md_chars]
                         + WINDOWS_TRUNCATION_MESSAGE
                     )
🤖 Prompt for AI Agents
In `@apps/backend/core/client.py` around lines 836 - 859, The current Windows
truncation logic fails when max_claude_md_chars <= 0 and ends up appending the
full claude_md_content; update the block around is_windows()/max_claude_md_chars
so that if max_claude_md_chars <= 0 you do not append CLAUDE.md at all (set
was_truncated = True), print a clear message (e.g., "CLAUDE.md: omitted (no
budget under Windows command-line limit)"), and only append claude_md_content
when max_claude_md_chars > 0 (truncating when necessary with
WINDOWS_TRUNCATION_MESSAGE); reference is_windows,
WINDOWS_MAX_SYSTEM_PROMPT_CHARS, base_prompt, WINDOWS_TRUNCATION_MESSAGE,
claude_md_content, and was_truncated to locate where to change the logic and
messages.

Comment on lines 726 to 733
childProcess = spawn(pythonCommand, [...pythonBaseArgs, ...args], {
cwd,
env: {
...env, // Already includes process.env, extraEnv, profileEnv, PYTHONUNBUFFERED, PYTHONUTF8
...pythonEnv, // Include Python environment (PYTHONPATH for bundled packages)
...mergedPythonEnv, // Python env with merged PATH (preserves augmented PATH entries)
...oauthModeClearVars, // Clear stale ANTHROPIC_* vars when in OAuth mode
...apiProfileEnv // Include active API profile config (highest priority for ANTHROPIC_* vars)
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Find pythonEnvManager.getPythonEnv() calls and implementation
rg -n "getPythonEnv" --type=ts -A5 -B5 | head -100

Repository: AndyMik90/Auto-Claude

Length of output: 10363


🏁 Script executed:

#!/bin/bash
# Look for pythonEnvManager definition and initialization
rg -n "pythonEnvManager\s*=" --type=ts -A3 -B3

Repository: AndyMik90/Auto-Claude

Length of output: 615


🏁 Script executed:

#!/bin/bash
# Check the file where pythonEnvManager is defined
fd pythonEnvManager --type=ts

Repository: AndyMik90/Auto-Claude

Length of output: 234


🏁 Script executed:

#!/bin/bash
# Read the getPythonEnv() method implementation
sed -n '690,750p' apps/frontend/src/main/python-env-manager.ts

Repository: AndyMik90/Auto-Claude

Length of output: 3204


🏁 Script executed:

#!/bin/bash
# Read more of the getPythonEnv() implementation to see all returned keys
sed -n '690,800p' apps/frontend/src/main/python-env-manager.ts

Repository: AndyMik90/Auto-Claude

Length of output: 4692


🏁 Script executed:

#!/bin/bash
# Look at agent-process.ts to see mergedPythonEnv construction and context
sed -n '700,750p' apps/frontend/src/main/agent/agent-process.ts

Repository: AndyMik90/Auto-Claude

Length of output: 2573


🏁 Script executed:

#!/bin/bash
# Look at env construction before it's passed to spawn
sed -n '650,730p' apps/frontend/src/main/agent/agent-process.ts | head -100

Repository: AndyMik90/Auto-Claude

Length of output: 3992


🏁 Script executed:

#!/bin/bash
# Check what extraEnv, profileEnv, and other env components contain
rg -n "extraEnv|profileEnv|oauthModeClearVars" apps/frontend/src/main/agent/agent-process.ts -B2 -A2 | head -80

Repository: AndyMik90/Auto-Claude

Length of output: 3624


🏁 Script executed:

#!/bin/bash
# Check setupProcessEnvironment to see what's set in env
sed -n '176,260p' apps/frontend/src/main/agent/agent-process.ts

Repository: AndyMik90/Auto-Claude

Length of output: 4017


Clarify redundant Python environment variable overrides and document override semantics.

mergedPythonEnv spreads after env (line 730), causing all keys to override env values. PATH is explicitly merged (lines 706-721) to preserve augmented entries, but other keys override unconditionally: PYTHONUNBUFFERED, PYTHONIOENCODING, and PYTHONUTF8 are redundantly set in both env and mergedPythonEnv. While new keys like PYTHONDONTWRITEBYTECODE and PYTHONNOUSERSITE should override consistently, remove the redundant duplication from setupProcessEnvironment() (lines 242-244) since getPythonEnv() now provides the canonical Python configuration. Update the comment on line 730 to document this override behavior or consider an explicit merge strategy for all Python-related keys to match PATH handling.

🤖 Prompt for AI Agents
In `@apps/frontend/src/main/agent/agent-process.ts` around lines 726 - 733, The
spawn call currently spreads env then mergedPythonEnv so mergedPythonEnv
unconditionally overrides keys from env (including PATH which you purposely
merged earlier), and setupProcessEnvironment() still injects duplicate Python
vars; remove the redundant PYTHON-specific assignments (e.g., PYTHONUNBUFFERED,
PYTHONIOENCODING, PYTHONUTF8) from setupProcessEnvironment() so
getPythonEnv()/getMergedPythonEnv (the code producing mergedPythonEnv) is the
canonical source, or alternatively change the spawn merge to explicitly merge
Python keys the same way PATH is merged; also update the inline comment near the
spawn (where env, mergedPythonEnv, oauthModeClearVars, apiProfileEnv are
combined) to clearly state that mergedPythonEnv has final precedence for
Python-related vars and PATH merging is preserved.

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

Labels

area/fullstack This is Frontend + Backend bug Something isn't working size/M Medium (100-499 lines)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Agent error: Claude code not found (Kanban doesn't have access to files)

1 participant