This PR updates the version to 0.0.19 after publishing to PyPI.
## Changes
- Updated version in `pyproject.toml`
- Updated version in `src/claude_code_sdk/__init__.py`
## Release Information
- Published to PyPI: https://pypi.org/project/claude-code-sdk/0.0.19/
- Install with: `pip install claude-code-sdk==0.0.19`
🤖 Generated by GitHub Actions
---------
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
## Summary
Fixes a critical deadlock issue that occurs when MCP servers produce
verbose stderr output. The SDK would hang indefinitely when the stderr
pipe buffer filled up.
## The Problem
The deadlock occurred due to sequential reading of subprocess streams:
1. SDK reads stdout completely before reading stderr
2. When stderr pipe buffer fills (64KB on Linux, 16KB on macOS),
subprocess blocks on write
3. Subprocess can't continue to stdout, parent waits for stdout →
**DEADLOCK** 🔒
## The Solution
Redirect stderr to a temporary file instead of a pipe:
- **No pipe buffer** = no possibility of deadlock
- Temp file can grow as needed (no 64KB limit)
- Still capture stderr for error reporting (last 100 lines)
- Works consistently across all async backends
## Implementation Details
- `stderr=tempfile.NamedTemporaryFile()` instead of `stderr=PIPE`
- Use `deque(maxlen=100)` to keep only recent stderr lines in memory
- Temp file is automatically cleaned up on disconnect
- Add `[stderr truncated, showing last 100 lines]` message when buffer
is full
## Testing
- Verified no deadlock with 150+ lines of stderr output
- Confirmed stderr is still captured for error reporting
- All existing tests pass
- Works with asyncio, trio, and other anyio backends
## Impact
- Fixes consistent hangs in production with MCP servers
- No functional regression - stderr handling is preserved
- Simpler than concurrent reading alternatives
- More robust than pipe-based solutions
Fixes the issue reported in Slack where SDK would hang indefinitely when
receiving messages from MCP servers with verbose logging.
🤖 Generated with [Claude Code](https://claude.ai/code)
---------
Co-authored-by: Claude <noreply@anthropic.com>
This PR updates the version to 0.0.18 after publishing to PyPI.
## Changes
- Updated version in `pyproject.toml`
- Updated version in `src/claude_code_sdk/__init__.py`
## Release Information
- Published to PyPI: https://pypi.org/project/claude-code-sdk/0.0.18/
- Install with: `pip install claude-code-sdk==0.0.18`
🤖 Generated by GitHub Actions
---------
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
## Summary
- Add `settings` field to `ClaudeCodeOptions` to expose the `--settings`
CLI flag
- Allow SDK users to specify custom settings configuration path
## Changes
- Added `settings: str | None = None` field to `ClaudeCodeOptions`
dataclass
- Added CLI argument conversion logic in `SubprocessCLITransport` to
pass `--settings` flag to Claude Code CLI
## Test plan
- [x] All existing tests pass
- [x] Linting passes (`python -m ruff check`)
- [x] Type checking passes (`python -m mypy src/`)
🤖 Generated with [Claude Code](https://claude.ai/code)
---------
Co-authored-by: Claude <noreply@anthropic.com>
This PR updates the version to 0.0.17 after publishing to PyPI.
## Changes
- Updated version in `pyproject.toml`
- Updated version in `src/claude_code_sdk/__init__.py`
## Release Information
- Published to PyPI: https://pypi.org/project/claude-code-sdk/0.0.17/
- Install with: `pip install claude-code-sdk==0.0.17`
🤖 Generated by GitHub Actions
---------
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
## Summary
- Replace asyncio.create_task() with anyio task group for trio
compatibility
- Update client.py docstring example to use anyio.sleep
- Add trio example demonstrating multi-turn conversation
## Details
The SDK already uses anyio for most async operations, but one line was
using asyncio.create_task() which broke trio compatibility. This PR
fixes that by using anyio's task group API with proper lifecycle
management.
### Changes:
1. **subprocess_cli.py**: Replace asyncio.create_task() with anyio task
group, ensuring proper cleanup on disconnect
2. **client.py**: Update docstring example to use anyio.sleep instead of
asyncio.sleep
3. **streaming_mode_trio.py**: Add new example showing how to use the
SDK with trio
## Test plan
- [x] All existing tests pass
- [x] Manually tested with trio runtime (created test script that
successfully runs multi-turn conversation)
- [x] Linting and type checking pass
🤖 Generated with [Claude Code](https://claude.ai/code)
This PR updates the version to 0.0.16 after publishing to PyPI.
## Changes
- Updated version in `pyproject.toml`
- Updated version in `src/claude_code_sdk/__init__.py`
## Release Information
- Published to PyPI: https://pypi.org/project/claude-code-sdk/0.0.16/
- Install with: `pip install claude-code-sdk==0.0.16`
🤖 Generated by GitHub Actions
---------
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
This PR updates the version to 0.0.14 after publishing to PyPI.
## Changes
- Updated version in `pyproject.toml`
- Updated version in `src/claude_code_sdk/__init__.py`
## Release Information
- Published to PyPI: https://pypi.org/project/claude-code-sdk/0.0.14/
- Install with: `pip install claude-code-sdk==0.0.14`
## Next Steps
After merging this PR, a release tag will be created automatically.
Signed-off-by: Lina <lina@anthropic.com>
Add critical safety mechanisms to the sequential stderr reading approach:
- 10MB memory limit on stderr collection with truncation message
- 30 second timeout protection to prevent hanging
- Proper exit code based error detection instead of string matching
- Debug logging for stderr on successful runs
- Better exception handling for edge cases
This addresses potential production issues while maintaining FastAPI compatibility.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
Remove anyio.create_task_group() from receive_messages() to fix the
RuntimeError "Attempted to exit cancel scope in a different task than
it was entered in" when using the SDK with FastAPI's SSE streaming.
The issue occurred because FastAPI can move async generators between
different asyncio tasks during the streaming lifecycle, which conflicts
with anyio's cancel scope tracking.
Changes:
- Remove task group usage from receive_messages()
- Read stderr sequentially after stdout completes
- Add test to ensure no task groups are used
- Fix existing test expectation for buffer overflow
This is a minimal fix that maintains compatibility while solving the
core issue. The trade-off is that stderr is read after stdout instead
of concurrently, but this is unlikely to cause issues in practice.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
Removed redundant comments that simply restate what the code is doing.
Kept only comments that provide valuable context or explain complex behavior.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
The CLIJSONDecodeError constructor expects an Exception as the second
argument, not None. Changed to pass a ValueError with details about
the buffer size limit being exceeded.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
Adds buffering to accumulate incomplete JSON messages that are split
across multiple stream reads due to asyncio's 64KB default buffer limit.
- Implement 1MB buffer to accumulate partial JSON
- Clear buffer on successful parse or size limit exceeded
- Add comprehensive tests for split JSON scenarios
Fixes CLIJSONDecodeError when reading large minified JSON files.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
The CLI only sends total_cost_usd, not cost_usd. This PR:
- Removes the non-existent cost_usd field from ResultMessage
- Makes total_cost_usd optional since it may be missing
- Handles GeneratorExit gracefully in subprocess transport
- Removes unnecessary cancel scope call
Fixes the error users were experiencing:
- KeyError: 'cost_usd'
- Field required [type=missing, input_value=...]
The anyio cancel scope error still appears in logs but doesn't affect functionality.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>