-
Notifications
You must be signed in to change notification settings - Fork 2.6k
fix: resolve Claude CLI --system-prompt flag error by passing via stdin #6536
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -141,7 +141,7 @@ describe("runClaudeCode", () => { | |
| expect(typeof result[Symbol.asyncIterator]).toBe("function") | ||
| }) | ||
|
|
||
| test("should handle platform-specific stdin behavior", async () => { | ||
| test("should pass system prompt and messages via stdin for all platforms", async () => { | ||
| const { runClaudeCode } = await import("../run") | ||
| const messages = [{ role: "user" as const, content: "Hello world!" }] | ||
| const systemPrompt = "You are a helpful assistant" | ||
|
|
@@ -160,7 +160,7 @@ describe("runClaudeCode", () => { | |
| results.push(chunk) | ||
| } | ||
|
|
||
| // On Windows, should NOT have --system-prompt in args | ||
| // Should NOT have --system-prompt in args | ||
| const [, args] = mockExeca.mock.calls[0] | ||
| expect(args).not.toContain("--system-prompt") | ||
|
|
||
|
|
@@ -181,13 +181,12 @@ describe("runClaudeCode", () => { | |
| results2.push(chunk) | ||
| } | ||
|
|
||
| // On non-Windows, should have --system-prompt in args | ||
| // Should NOT have --system-prompt in args (same behavior for all platforms now) | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same here - this comment still mentions platform differences that we've eliminated. Consider: |
||
| const [, args2] = mockExeca.mock.calls[0] | ||
| expect(args2).toContain("--system-prompt") | ||
| expect(args2).toContain(systemPrompt) | ||
| expect(args2).not.toContain("--system-prompt") | ||
|
|
||
| // Should only pass messages via stdin | ||
| expect(mockStdin.write).toHaveBeenCalledWith(JSON.stringify(messages), "utf8", expect.any(Function)) | ||
| // Should pass both system prompt and messages via stdin (same as Windows) | ||
| expect(mockStdin.write).toHaveBeenCalledWith(expectedStdinData, "utf8", expect.any(Function)) | ||
| }) | ||
|
|
||
| test("should include model parameter when provided", async () => { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -151,16 +151,10 @@ function runProcess({ | |
| maxOutputTokens, | ||
| }: ClaudeCodeOptions & { maxOutputTokens?: number }) { | ||
| const claudePath = path || "claude" | ||
| const isWindows = os.platform() === "win32" | ||
|
|
||
| // Build args based on platform | ||
| // Build args - no longer passing system prompt as command line argument | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The comment could be more descriptive about why we're making this change. Consider: This would help future maintainers understand the reasoning behind this architectural decision. |
||
| const args = ["-p"] | ||
|
|
||
| // Pass system prompt as flag on non-Windows, via stdin on Windows (avoids cmd length limits) | ||
| if (!isWindows) { | ||
| args.push("--system-prompt", systemPrompt) | ||
| } | ||
|
|
||
| args.push( | ||
| "--verbose", | ||
| "--output-format", | ||
|
|
@@ -193,17 +187,12 @@ function runProcess({ | |
| timeout: CLAUDE_CODE_TIMEOUT, | ||
| }) | ||
|
|
||
| // Prepare stdin data: Windows gets both system prompt & messages (avoids 8191 char limit), | ||
| // other platforms get messages only (avoids Linux E2BIG error from ~128KiB execve limit) | ||
| let stdinData: string | ||
| if (isWindows) { | ||
| stdinData = JSON.stringify({ | ||
| systemPrompt, | ||
| messages, | ||
| }) | ||
| } else { | ||
| stdinData = JSON.stringify(messages) | ||
| } | ||
| // Pass both system prompt and messages via stdin for all platforms | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These two comment lines could be consolidated for brevity: |
||
| // This avoids command line argument issues with --system-prompt flag | ||
| const stdinData = JSON.stringify({ | ||
| systemPrompt, | ||
| messages, | ||
| }) | ||
|
|
||
| // Use setImmediate to ensure process is spawned before writing (prevents stdin race conditions) | ||
| setImmediate(() => { | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This comment references Windows-specific behavior that no longer exists. Could we update it to reflect the unified behavior?