On this page
Synchronous session wrapper that bridges the async Claude Code stream-json protocol to a blocking iterator-based interface.
#claudestream._sync_session
#claudestream._sync_session
Synchronous session wrapper that bridges the async Claude Code stream-json protocol to a blocking iterator-based interface.
#SyncSession
Synchronous session managing a Claude Code subprocess.
Wraps AsyncSession by running it on a dedicated event loop thread.
Usage::
config = SessionConfig(model="sonnet", profile="default") with SyncSession(config) as session: for event in session.send("hello"): print(event)
#_run_loop
def _run_loop(self) -> NoneTarget for the event loop thread.
#_ensure_loop
def _ensure_loop(self) -> asyncio.AbstractEventLoopStart the event loop thread if not already running.
#_run_coro
def _run_coro(self, coro)Run a coroutine on the event loop thread and wait for the result.
#close
def close(self) -> NoneShut down the session, subprocess, and event loop thread.
#session_id
def session_id(self) -> str | None#model_name
def model_name(self) -> str | None#tools
def tools(self) -> list[str]#claude_version
def claude_version(self) -> str | None#last_result
def last_result(self) -> Result | None#files_modified
def files_modified(self) -> set[str]All files written or edited during this session (absolute paths, deduplicated).
#stderr_lines
def stderr_lines(self) -> list[str]#turn_count
def turn_count(self) -> int#total_tokens
def total_tokens(self) -> int#total_cost_usd
def total_cost_usd(self) -> float#sandbox
def sandbox(self) -> Sandbox | None#user_tools
def user_tools(self) -> list[Tool]#is_alive
def is_alive(self) -> bool#active_turn
def active_turn(self) -> bool#cancelled
def cancelled(self) -> bool#process_pid
def process_pid(self) -> int | None#cwd
def cwd(self) -> str#mcp_servers
def mcp_servers(self) -> list[str]#permission_mode
def permission_mode(self) -> str#config
def config(self) -> SessionConfig#cancel
def cancel(self, force: bool=False) -> NoneCancel the current operation.
Args:
force: If False, close stdin (graceful). If True, terminate subprocess.
#ask
def ask(self, prompt: str | list) -> AskResultSend a prompt and return the complete response text with metadata.
#send
def send(self, prompt: str | list, *, raw: bool=False) -> Iterator[Event]Send a message and yield events until the turn completes.
Args:
prompt: The message to send. Can be a plain string or a list of
content blocks (dicts) for multimodal input.
raw: If True, yield raw protocol events. If False, yield flattened events.
Yields:
- Event objects until a Result event is received.
#on
def on(self, event_type: type[Event], handler: Callable[[Any], None]) -> NoneRegister a callback for a specific event type.
#on_turn_complete
def on_turn_complete(self, hook: Callable) -> NoneRegister a hook that fires after each turn completes (after Result event).
Hook signature: def hook(session, result). The session argument is this SyncSession instance (not the underlying AsyncSession).
#on_error
def on_error(self, hook: Callable) -> NoneRegister a hook that fires when a turn fails with an exception.
Hook signature: def hook(session, exception). The session argument is this SyncSession instance (not the underlying AsyncSession).
#on_close
def on_close(self, hook: Callable) -> NoneRegister a hook that fires when the session closes.
Hook signature: def hook(session). The session argument is this SyncSession instance (not the underlying AsyncSession).
#respond_allow
def respond_allow(self, request_id: str, updated_input: dict, *, updated_permissions: list[dict] | None=None) -> NoneAllow a permission request, optionally applying permission-rule updates.
#respond_deny
def respond_deny(self, request_id: str, message: str='Denied by user') -> NoneDeny a permission request.
#respond_dialog
def respond_dialog(self, request_id: str, result: Any) -> NoneComplete a user dialog request with the user's chosen result.
#respond_dialog_cancelled
def respond_dialog_cancelled(self, request_id: str) -> NoneCancel a user dialog request; the CLI applies the dialog's default behavior.
#interrupt
def interrupt(self, *, timeout: float=30.0) -> list[str]Interrupt the running turn. Returns any still-queued user messages.
#set_permission_mode
def set_permission_mode(self, mode: str) -> NoneChange the permission mode mid-session.
#set_model
def set_model(self, model: str | None) -> NoneSwitch the model mid-session. None resets to the CLI default.
#get_context_usage
def get_context_usage(self, *, timeout: float=30.0) -> ContextUsageQuery the model's current context-window usage.