feat: allow claude code process to run as a custom user (#133) (#134)
Some checks are pending
Lint / lint (push) Waiting to run
Test / test-e2e (3.12) (push) Blocked by required conditions
Test / test-e2e (3.13) (push) Blocked by required conditions
Test / test (3.10) (push) Waiting to run
Test / test (3.11) (push) Waiting to run
Test / test (3.12) (push) Waiting to run
Test / test (3.13) (push) Waiting to run
Test / test-e2e (3.10) (push) Blocked by required conditions
Test / test-e2e (3.11) (push) Blocked by required conditions
Test / test-examples (3.10) (push) Blocked by required conditions
Test / test-examples (3.11) (push) Blocked by required conditions
Test / test-examples (3.12) (push) Blocked by required conditions
Test / test-examples (3.13) (push) Blocked by required conditions

This commit is contained in:
Dan Siwiec 2025-09-16 16:40:19 -07:00 committed by GitHub
parent 3010aaf092
commit fd98d12f94
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 41 additions and 0 deletions

View file

@ -201,6 +201,7 @@ class SubprocessCLITransport(Transport):
stderr=stderr_dest,
cwd=self._cwd,
env=process_env,
user=self._options.user,
)
if self._process.stdout:

View file

@ -298,6 +298,8 @@ class ClaudeCodeOptions:
# Hook configurations
hooks: dict[HookEvent, list[HookMatcher]] | None = None
user: str | None = None
# SDK Control Protocol
class SDKControlInterruptRequest(TypedDict):

View file

@ -352,3 +352,41 @@ class TestSubprocessCLITransport:
assert env_passed["PATH"] == os.environ["PATH"]
anyio.run(_test)
def test_connect_as_different_user(self):
"""Test connect as different user."""
async def _test():
custom_user = "claude"
options = ClaudeCodeOptions(user=custom_user)
# Mock the subprocess to capture the env argument
with patch(
"anyio.open_process", new_callable=AsyncMock
) as mock_open_process:
mock_process = MagicMock()
mock_process.stdout = MagicMock()
mock_stdin = MagicMock()
mock_stdin.aclose = AsyncMock() # Add async aclose method
mock_process.stdin = mock_stdin
mock_process.returncode = None
mock_open_process.return_value = mock_process
transport = SubprocessCLITransport(
prompt="test",
options=options,
cli_path="/usr/bin/claude",
)
await transport.connect()
# Verify open_process was called with correct user
mock_open_process.assert_called_once()
call_kwargs = mock_open_process.call_args.kwargs
assert "user" in call_kwargs
user_passed = call_kwargs["user"]
# Check that user was passed
assert user_passed == "claude"
anyio.run(_test)