claudestream v0.14.2 /Changelog
On this page

#Changelog

#0.14.2

Ships the second machine-local path fix: probe_user_dialogs.py now requires --captures-dir instead of defaulting to an operator scratchpad path.

Context

0.14.1 fixed a cassette privacy leak and added a repo-wide hygiene guard. That guard immediately found a second leak of the same class: scripts/probe_user_dialogs.py hardcoded an absolute operator scratchpad path (including a session UUID) as the default for its captures directory. The fix landed right after 0.14.1 was cut, so the offending path still ships in the 0.14.1 sdist. 0.14.2 exists to get the fixed artifact published.

#Fixes

  • A second machine-local path is gone from the published sdist. scripts/probe_user_dialogs.py defaulted its capture directory to an absolute path naming the author's account; it is now a required --captures-dir argument. The hygiene guardrail was extended from the recorded cassettes to every git-tracked text file, which is what found it.

#0.14.1

Privacy fix: the published sdist no longer carries the recording machine's paths or private tool inventory.

Context

An audit of the 0.14.0 test infrastructure found that the VCR recorder's scrubber emptied only list-valued inventory keys. memory_paths arrives from the CLI as a dict, so it was copied verbatim and a real /tmp/.../-home--Projects-claudestream/... path shipped inside the committed cassette -- and inside the published sdist, which packages tests/. The cassette also carried the recording machine's full tool inventory.

Scrubbing is now type-agnostic (dict, list, str) rather than list-shaped, the tools inventory is filtered to a public-tool allowlist, and both cassettes were re-recorded through the credential-less free lane (total_cost_usd 0, zero API spend). tests/test_cassette_hygiene.py is the backstop that does not need to know the schema: it greps every committed cassette for home directories, temp directories, $HOME, the operator username as a path segment and absolute-path shapes, so the next unknown protocol key cannot leak silently.

The same audit found the spend guard weaker than advertised, all fixed here and pinned by tests: tests/test_integration.py hardcoded an absolute path to the real binary (the poisoned PATH only intercepts name lookups, so 19 tests were outside the guard); the guard hooks lived in tests/conftest.py, so pytest scripts/ ran unguarded; the opt-in assertion checked only a skip count, which a broken local profile reproduces; and two spend-capable operator scripts in scripts/ were named test_*.py, so pytest collected them.

#Fixes

  • Fixed a privacy defect in the published sdist. The 0.14.0 tarball's test cassettes carried the recording machine's filesystem paths and private tool inventory: the recorder scrubbed only list-valued inventory keys, and memory_paths arrives as a dict. Scrubbing is now type-agnostic, the tools inventory is filtered to a public-tool allowlist, both cassettes were re-recorded, and a hygiene test greps every committed cassette for machine-local shapes.

#0.14.0

Agent definitions are schema-validated at load, the CLI runs on strictcli 0.36, and the test suite can no longer spend money.

Context

This release carries the strictspec at-rest gate for .agent.json documents (a breaking change: an integer format_version is now required), the strictcli 0.36 command-classification migration and its dependency floor, two new documentation guides, and a fix that makes agent discovery report the deprecated budget fields as helpfully as load_agent already did.

Behind that, the test suite changed shape. Integration tests used to drive the real claude binary against a real profile on every full-suite run, so the release gate itself billed a real account. They are now opt-in behind CLAUDESTREAM_INTEGRATION=1, backed by a poisoned PATH shim so nothing else can reach a real binary either, and a recorded-replay (VCR) lane covers the wire protocol -- real subprocess, real pipes, real control round-trips -- from committed cassettes at zero cost.

#Breaking

  • Agent definitions are now schema-validated at load. .agent.json documents loaded via load_agent/discover_agents/the agent CLI are validated against a strictspec schema before decoding: they now REQUIRE an integer format_version (currently 1), and unknown keys (with did-you-mean hints) or wrong-typed fields are rejected with hard AgentValidationErrors. Stamp existing agent files with "format_version": 1 one time.

#Features

  • Architecture and agents guides. The documentation site gains a guide to claudestream's four layers and a guide to agent definitions, plus a generated table of every stream event type.
  • Fuller CLI help text. Every command and flag description was expanded, so claudestream <command> --help explains what a command does and when to reach for it.

#Fixes

  • The CLI works again on strictcli 0.36.0. strictcli made per-command effect classification mandatory, which hard-errored claudestream's command registration -- claudestream --help, every subcommand and any import of claudestream._cli failed. All 11 commands are now classified: the six that spawn a Claude Code subprocess are mutating, the five inspection commands are read_only. No command prompts for confirmation.
  • Agent discovery now explains the deprecated budget fields. A .agent.json still using max_cost_usd, max_turns or max_tokens reported a generic unknown-key error when found by discover_agents (or claudestream agent list) while load_agent gave the migration hint. Both paths now name the replacement threshold fields.
  • Installs can no longer resolve a strictcli too old to run claudestream. The manifest now declares strictcli>=0.36.0; below that, command registration fails and every CLI invocation errors on import.

#0.13.1

Real-CLI integration tests now skip gracefully when the claude binary or a claudewheel profile is unavailable, so CI and credential-less environments no longer fail the suite.

Context

The 0.13.0 release tagged and pushed successfully but its PyPI and npm publish was blocked because the CI test suite failed on the GitHub runner: the newly scaffolded full-suite CI ran the real-CLI integration tests in a credential-less environment with no claude binary and no claudewheel profiles, and claudewheel 0.22's resolve_profile raises instead of failing soft, turning what should be skips into 20 hard errors. This hotfix adds a shared skip guard so those tests skip gracefully when their external prerequisites are absent, unblocking the publish that the 0.13.0 CI gate held back. bump = hotfix because the change is test-infrastructure only (no user-facing changelog entries).

#Infrastructure

  • Real-CLI integration tests now skip gracefully when the claude binary or a claudewheel profile is unavailable, so CI and credential-less environments no longer fail the suite.

#0.13.0

Control-protocol extensions for interactive clients: interrupt, live model and permission-mode switching, context usage, user dialogs, enriched permission prompts, and renderer observability.

Context

These additions power alternative frontends that drive the claude CLI directly. AskUserQuestion is answered by feeding the choice back through a permission updatedInput, so interactive tools resolve without a separate answer channel. A correlation registry tracks pending control requests with restart-safe hard failures, so a dropped or restarted session surfaces an explicit error rather than a silently unresolved future.

#Breaking

  • Breaking. Renamed --no-color flag to --color (default: true) across all commands. Use --no-color to disable color output.

#Features

  • New feature. Added __version__ attribute to the claudestream package.
  • Control-request wire structs. New ControlRequest message struct and a ControlResponse.error field expose the CLI control protocol for interrupt, model, and mode requests.
  • Control-request correlation. Sessions can issue correlated control requests with pending-future tracking, turn-loop and between-turns response resolution, timeouts, and restart/close safety.
  • Interactive session controls. interrupt(), set_permission_mode(), set_model(), and get_context_usage() are now available on both AsyncSession and SyncSession, and SessionConfig.permission_mode sets the initial permission mode via --permission-mode.
  • Dialog and enriched-permission responses. New DialogCompleted and DialogCancelled messages answer user dialogs, AllowPermission accepts updated_permissions to apply permission-rule updates on allow, and InitializeRequest can declare supported_dialog_kinds.
  • Tool-permission prompts now decode correctly. The current Claude CLI sends permission prompts as can_use_tool; these now surface as PermissionRequest (with new fields like permission_suggestions, display_name, and requires_user_interaction) instead of being missed. A new UserDialogRequest event carries CLI-driven user dialogs.
  • User-dialog handling on sessions. respond_dialog() and respond_dialog_cancelled() answer dialog requests, respond_allow() accepts updated_permissions, and SessionConfig.supported_dialog_kinds declares which dialogs the consumer can render (forcing the initialize handshake). Available on both AsyncSession and SyncSession.
  • Renderer observability. ToolResult now carries tool_name (correlated from the matching ToolUse), and Result exposes per-model model_usage from the CLI's modelUsage payload.
  • Permission interception. New SessionConfig.intercept_permissions routes permission prompts and interactive tools like AskUserQuestion to the consumer as PermissionRequest events.
  • Tool error signal. ToolResult and ToolResultBlock now expose is_error, so consumers can distinguish failed tool executions from successful ones.

#Fixes

  • Fix. ToolSchema fields description, input_schema, and server are now optional, supporting name-only tool entries.

#0.12.2

Fix liveness probe to use event-based timeout instead of CPU-based polling

#Fixes

  • Fix. Liveness probe now uses event-based timeout instead of CPU monitoring, correctly detecting I/O-bound subprocess hangs.

#0.12.1

Fix uv.lock local paths and Usage struct documentation

#Fixes

  • Fix. Regenerated uv.lock to resolve dependencies from PyPI instead of local editable paths, fixing CI test failures.
  • Fix. Clarified Usage struct docstring to explain context-dependent semantics (per-call vs cumulative).

#0.12.0

Observe-not-limit budget redesign

Context

Budget fields replaced with threshold-based observation. Budget no longer kills sessions -- it emits BudgetThreshold events.

#Breaking

  • Breaking. Budget fields max_cost_usd, max_turns, max_tokens replaced with threshold-based observation: cost_thresholds, turn_thresholds, token_thresholds. Budget no longer kills sessions — it emits BudgetThreshold events when thresholds are crossed.

#Features

  • New. session.total_cost_usd property for cumulative session cost tracking.
  • New. SessionConfig.cost_log_path enables per-turn JSONL cost logging with session metadata.
  • New. SyncSession.total_cost_usd property.

#Fixes

  • Fix. Token accumulation no longer double-counts — usage fields are session-cumulative, not per-turn.
  • Fix. Pass all SessionConfig fields through agent invocation merge.

#0.11.0

Transparent subprocess retry and structured logging

Context

Adds automatic subprocess retry on stuck detection and structured logging for liveness probe events.

#Features

  • New. Transparent subprocess retry when stuck detection triggers, preventing session hangs.
  • New. Structured logging for liveness probe events, subprocess retry, restart, and session start.

#0.10.0

Liveness probe, MCP multi-server handshake fix

#Features

  • Liveness check. Subprocess CPU monitoring via psutil detects stuck Claude CLI processes. When the subprocess is alive but at 0% CPU (idle), it is killed and a clear error is raised instead of hanging forever.

#Fixes

  • MCP multi-server handshake. Sessions with tools from multiple MCP servers no longer hang. The handshake now waits for all servers to complete tools/list before proceeding.

#0.9.0

#Features

  • SyncSession now exposes all 19 AsyncSession properties including turn_count, total_tokens, sandbox, and config.
  • SDK-registered MCP tools are now immediately visible to the model without requiring a ToolSearch call.
  • Expanded CLI help descriptions for agent subcommands.

#Fixes

  • invoke_agent now correctly passes tool_context and inject metadata to MCP tools.

#0.8.0

#Features

  • Documentation. README.md and CLAUDE.md are now auto-generated from selfdoc templates with comprehensive examples, architecture narrative, and API reference tables.

#Fixes

  • Bug fix. Custom tools registered via @tool are now visible to the model. The SDK MCP handshake was incomplete -- claudestream now sends mcp_set_servers after initialization and handles the full MCP protocol negotiation (initialize, notifications/initialized, tools/list).
  • Bug fix. MCP handshake unit and integration tests verifying tool registration end-to-end.

#0.7.7

#Features

  • **--from-pr CLI flag.** All commands (send, stream, events, repl, ask) now accept --from-pr to resume from a PR-linked session.

#0.7.6

#Fixes

  • Fixed MCP tool visibility. Tools registered via @tool are now visible to the Claude Code model. The --permission-prompt-tool stdio flag was missing when MCP tools were registered without sandbox restrictions.

#0.7.5

#Features

  • npm package. npx claudestream now works. The npm package is a thin CLI wrapper that shells out to the Python claudestream command.

#0.7.4

#Fixes

  • Fixed prompt template false positives. resolve_prompt() no longer flags {word} patterns that were introduced by variable substitution itself.

#0.7.3

#Features

  • Agent discovery from custom paths and packages. discover_agents() now accepts paths= for custom directories and packages= for Python package resources via importlib.resources. Deduplicates by name with warnings on conflicts. load_agent() gains a cwd parameter for consistent bare name resolution.

#0.7.2

#Features

  • Tool context injection. @tool("server", inject=["ctx"]) explicitly declares parameters injected from SessionConfig.tool_context. Injected params are hidden from the model's schema. Hard error when context is required but missing.

#0.7.1

#Features

  • File write tracking. New FileWrite and FileEdit derived events emitted when Claude writes or edits files. session.files_modified accumulates all modified paths with absolute path resolution.
  • Lifecycle hooks. on_turn_complete, on_error, on_close hooks for post-turn cleanup, error handling, and session teardown. Supports both sync and async hooks.

#Fixes

  • Removed CLI output truncation. Tool results and thinking content are now printed in full, never truncated.
  • Editable install version freshness. CLI version now read from pyproject.toml at runtime, eliminating stale version after editable install bumps.

#0.7.0

#Breaking

  • SessionConfig. Sessions, print_prompt, and invoke_agent now accept a single SessionConfig struct instead of individual parameters.
  • Required fields. Tool.server, ToolSchema.server, and AgentDefinition.version no longer have defaults — callers must specify them explicitly.
  • **Removed SandboxConfig.** AgentDefinition.sandbox now uses Sandbox directly. JSON agent definitions with partial sandbox fields decode correctly.

#Features

  • Declarative flag registry. All ~45 Claude CLI flags are now typed ProcessConfig fields with a declarative registry in build_argv(). --verbose and --include-partial-messages are now configurable.
  • Expanded exports. Message types, protocol functions, option structs, BUILTIN_TOOLS, ProcessConfig, and ProcessManager now exported from the top-level package.
  • **Agent definitions gain mcp and stream fields.** AgentDefinition now accepts McpOptions and StreamOptions for MCP server config and stream behavior.
  • Budget enforcement. Budget.max_cost_usd wired to --max-budget-usd. Runtime enforcement of max_turns and max_tokens with ClaudeStreamError on exceeded limits.
  • **Enriched AskResult.** Now includes num_turns, duration_api_ms, stop_reason, result, api_error_status, and subtype from the Result event.
  • Session observability. New properties: sandbox, user_tools, is_alive, active_turn, cancelled, process_pid, cwd, mcp_servers, permission_mode, config, turn_count, total_tokens. SyncSession.stderr_lines now available.
  • Tool decorator expansion. @tool now handles Optional, Literal, Enum, list[dict], dict[str,T], default values, and docstring-based parameter descriptions. Tool results are JSON-serialized for dict/list returns. New collect_tools(module) utility.
  • **Multimodal send().** send() and ask() now accept str | list for content, enabling image blocks and structured content.
  • **SDK hooks and HookEvent.** New hooks parameter on SessionConfig wired to InitializeRequest. HookEvent type for lifecycle events.
  • Agent discovery. .claudestream/agents/ convention with bare name resolution. New discover_agents() function. CLI commands: agent list, agent info, agent validate.
  • Configurable constants. ProcessLimits controls buffer size, shutdown timeout, version check timeout, and health timeout. EventPrinter truncation lengths configurable. SyncSession poll and join timeouts configurable.
  • New CLI commands. claudestream ask (one-shot), claudestream doctor (health check), claudestream config (show resolved config).

#0.6.2

#Fixes

  • Stricter agent validation. CLI agent run now fails early with a clear message when no model is specified. invoke_agent raises ValueError listing any tools missing handlers.

#0.6.1

#Features

  • Session resumption. New resume_session_id parameter and --resume CLI flag to continue a previous Claude Code session.

#0.6.0

#Breaking

  • Sandbox system. Replaced the Policy system with a unified Sandbox API combining tool allow-lists, --bare mode, and filesystem write-path scoping.

#Features

  • Migrated to msgspec. All event, message, and content block types converted from dataclasses to msgspec Structs for faster parsing and better type validation.
  • SDK MCP tool registration. Register custom host-handled tools via @tool decorator or explicit schema. Full lifecycle: initialize handshake, tools/list, tools/call with async/sync handler support.
  • **ask() convenience method.** Send a prompt and get back an AskResult with text, usage, cost, and duration — no manual event collection needed.
  • Agent definition toolkit. Declarative AgentDefinition with prompt templates, tool schemas, sandbox config, and budget constraints. Load from .agent.json files. New claudestream agent run CLI command.

#0.5.1

#Fixes

  • Fix. --system-prompt no longer adds --bare, which was blocking OAuth authentication. Uses --append-system-prompt instead.

#0.5.0

#Breaking

  • Breaking. model and profile are now required parameters in the library API (AsyncSession, SyncSession, print_prompt).

#Features

  • New feature. SyncSession no longer uses a threading lock. Queue reads have a timeout to prevent infinite blocking. Thread startup uses threading.Event instead of busy-wait.
  • New feature. All events are now yielded to consumers, including SystemInit and auto-handled PermissionRequest. No more silent event filtering.
  • New feature. session.cancel(force=False) method on both AsyncSession and SyncSession. Graceful mode closes stdin; force mode sends SIGTERM.
  • New feature. All CLI commands now handle every event type. RateLimit, ApiRetry, Thinking, and PermissionRequest print to stderr instead of being silently dropped.
  • New feature. --system-prompt / -s flag on all CLI commands.
  • New feature. --stdin flag on send, stream, and events commands for piped input.
  • New feature. ANSI color output with TTY auto-detection, --no-color flag, and NO_COLOR env var support.

#Fixes

  • Fix. Removed unused imports, fixed inconsistent ToolResult truncation, fixed ellipsis always showing on short thinking blocks, added warning for unknown content block types.

#0.4.0

#Breaking

  • Breaking. --profile and --model are now required flags on all commands. No implicit defaults.

#Features

  • New feature. --footer/--no-footer flag on all commands. Cost and timing metadata now goes to stderr.
  • New feature. REPL shows actual model name after first response instead of \default\.

#Fixes

  • Fix. All CLI commands now handle errors gracefully instead of showing Python tracebacks.
  • Fix. Commands no longer silently swallow responses when streaming is unavailable (e.g., authentication errors).
  • Fix. Authentication failures now produce an actionable error message instead of silent empty output.
  • Fix. Subcommand parse errors now suggest the correct subcommand help (requires strictcli >= 0.8.6).

#0.3.0

#Features

  • New feature. Per-event INFO logging for all event types (Thinking, ToolUse, ToolResult, Result, ApiRetry, RateLimit) and a startup health probe that warns after 30s with no events.

#Fixes

  • Fix. Drain subprocess stderr to prevent pipe buffer deadlock that caused sessions to hang indefinitely.
  • Fix. Parse rate_limit_event type and system rate_limit subtype correctly — rate limit events were silently dropped as UnknownEvent.

#0.2.1

#Fixes

  • Fix. send command no longer prints response text twice.

#0.2.0

#Features

  • New feature. --profile flag for claudewheel profile selection — sets CLAUDE_CONFIG_DIR and OAuth token for the Claude subprocess.

#0.1.1

#Fixes

  • Fix. Session no longer hangs during initialization -- SystemInit is now captured lazily on first send().
  • Fix. Extended thinking responses no longer crash -- increased subprocess readline buffer to 16MB.

#0.1.0

#Features

  • Async and sync session APIs (AsyncSession, SyncSession) for multi-turn conversations with Claude Code
  • Configurable permission policy system (allow_all, deny_all, allow_builtins, allow_list, custom callbacks)
  • CLI with 4 commands: send, stream, events, repl
  • Subprocess lifecycle management with graceful shutdown
  • One-shot print_prompt() convenience function for simple use cases
  • Typed event models for all Claude Code stream-json event types
  • Real-time streaming token support via StreamDelta events
Search