Changelog
3.4.12
Section titled “3.4.12”- BYOT/TUI: Log resolved environment after hub registration and in session traces – Used
resolved_envinstead of the optionalenvoverride parameter (which defaults toNone) inrun_client()’s post-registrationconnected, ready for jobslog message, forwardedByotService._envtorun_client()when explicitly set, and fell back toapp.resolved_environmentwhenapp.config.environmentisNoneinSessionScreen._collect_trajectory().
3.4.11
Section titled “3.4.11”- BYOT/CLI: Fail-fast
wait_connected()handshake, 30s CLI timeout, and bootstrap cleanup – RacedByotService.wait_connected()against the background_run()task so auth or startup failures raise immediately with a descriptive error instead of waiting for the full timeout, increased thesec-geminiCLI BYOT handshake timeout from 10s to 30s (BYOT_HANDSHAKE_TIMEOUT_SECONDS = 30.0) to tolerate cold OIDC token fetches, cancelled pending background venv bootstrap tasks before removing the venv on shutdown, and suppressed falsepython_venv_removedlog messages when no owned venv existed on disk. - SDK/RPC: Refresh OIDC token and gRPC channel on stream reconnect – Checked JWT
expclaim (with 30s leeway) onSEC_GEMINI_OIDC_TOKENand supported both string and listaudclaims so expired environment tokens automatically fall back to freshgcloud/ ADC identity tokens, and addedGrpcTransport.reconnect()invoked fromRpcClient._listener_loopwhen reconnecting after an initial stream disconnect so long-running sessions (>1 hour) do not reuse expired static credentials. - SDK/Config: Refine
internal-no-internetresolution priority and upload metadata – Prioritized explicitSEC_GEMINI_PROJECT_NUMBERoverrides ahead of corp hostname heuristics and shared GSLB hub fallbacks inresolve_environment(), forwarded the resolved environment torun_client(), and includedx-sec-gemini-envmetadata inSessionFiles.upload_file().
3.4.10
Section titled “3.4.10”- SDK/TUI/BYOT:
internal-no-internetenvironment support – Addedinternal-no-internetenvironment and endpoint resolution for isolated Corp Run deployments (api-hub-394056583131.cr.gclb.googandbringyourowntool-hub-394056583131.cr.gclb.goog), including CLI--envsupport,SEC_GEMINI_PROJECT_NUMBERdetection, and TUI status footer styling. - SDK: Multi-day cold-sleep (
PAUSED) andSelfReflectionAgentstreaming support – ExtendedSessionMessagesstreaming to keep watches active acrossJobStatus.PAUSEDcold-sleep suspensions (PAUSED_SILENCE_HEARTBEAT_TIMEOUT = 300.0) and handle post-responseself_reflect/session_reviewfollow-up turns without prematurely terminatingFOLLOW_TURNstreams.
- BYOT/Tools: Harden workstation tools and system info on NFS filesystems – Replaced unhashable
Nonetracking for oversized files (>50 MB) with an $O(1)$stat_fingerprint_file()check (file size,st_mtime_ns,st_ctime_ns,st_ino, and 4 KB head/middle/tail samples) sowrite_file,append_file, andsearch_and_replacework on >50 MB files without reading the entire file over NFS while preserving read-before-write and external modification detection. Offloadedcollect_system_info()inBackend.send_prompt()to a worker thread viaasyncio.to_thread(), added--no-optional-lockstogit status --porcelainto avoid.git/index.lockcontention on NFS, boundedsearch_file_contentandsearch_filedirectory walks toMAX_WALK_ENTRIES = 10,000, and hardened directory walks against stale NFS file handles (ESTALE/ETIMEDOUT). - BYOT: Enforce client priority in
_lookup_toolacross prefix-stripped candidates – Fixed tool lookup ordering insec_gemini.byot.client._lookup_toolso an earlier MCP client’s prefixed tool (e.g.workstation_runon client 0) takes precedence over a later MCP client’s unprefixed tool (runon client 1), matching_handle_list_toolsdeduplication order.
Changed
Section titled “Changed”- SDK/Config: Detect
.roam.internaland.roam.corp.google.comas internal environment – Roaming Googler devices whose hostname or FQDN ends with.roam.internalor.roam.corp.google.comnow automatically resolve to theinternalenvironment by default.
- BYOT: OIDC fallback timeout & automatic JWT token refresh – Bounded
gcloud auth print-identity-tokenfallback calls with a 10s timeout (GCLOUD_TOKEN_TIMEOUT_SECONDS = 10.0) so unauthenticatedgcloudprompts cannot hang startup indefinitely, and added automatic JWT expiry inspection and refresh in_StaticTokenAuthPluginfor long-lived sessions. - BYOT: Startup MCP introspection timeout & offline external server resilience – Bounded startup tool introspection (
MCP_INTROSPECTION_TIMEOUT_SECONDS = 20.0) and initial client entry inByotServiceso a temporarily unreachable or hung external--mcpserver does not abort BYOT startup, allowingsession_guardto connect it lazily when available. - BYOT: Reconnect backoff jitter & infinite default CLI retries – Added ±20% randomized jitter (
_jittered_backoff) toByotServicereconnect sleeps to prevent thundering herds after hub restarts, and changed the standalonesec-gemini-byotCLI defaultMAX_RETRIESfrom5to-1(infinite retries across transient Wi-Fi/VPN drops or laptop sleep/wake cycles). - BYOT: Tool name deduplication & resource client route caching – Deduplicated clashing stripped tool names in
_handle_list_tools(matching_index_toolsrouting priority) and cached resource URI -> MCP client routes across_handle_list_resourcesand_handle_read_resourceto avoid $O(N)$list_resourcesfan-out on cache hits. - BYOT: Pong liveness watchdog for half-open gRPC streams – Added a stream activity watchdog (
PONG_TIMEOUT_SECONDS = 35.0) across_process_jobsand_ping_loopso half-open TCP blackholes wherestream.writesucceeds locally without any incomingPongorJobRequestfrom the hub trigger automatic stream teardown and reconnection. - BYOT: Bounded registration handshake timeout for fast IPv4 fallback – Wrapped the registration handshake (
stream.write+stream.read) inrun_clientwithREGISTRATION_TIMEOUT_SECONDS = 10.0so an IPv6 blackhole or hung primary target cancels the registration stream after 10s and fails over immediately to theipv4:fallback target.
- BYOT:
mcp2.x andfastmcp4.x compatibility & major-version bounds – FixedImportError: cannot import name 'McpError' from 'mcp.shared.exceptions'when runningsec-gemini-byotviauvxagainstmcp >= 2.0. Added compatibility acrossmcp1.x and 2.x (McpError/MCPError,JSONRPCDispatcherand wrapped context streams,"Session not found"404 responses, andby_alias=Truewire serialization for snake_casemcp2.x Pydantic models), boundedmcp<2.0andfastmcp<4.0in package metadata, and importedsec_gemini.byot.clienteagerly inByotService.
Changed
Section titled “Changed”- CLI:
--force-load-skills– New flag that preloads every skill passed via--skill/--skillsinto the agent’s context from the start, instead of letting the agent decide when to load them. It is off by default. SDK users can opt in withBackend.load_local_skills(paths, force_load=True), which makessend_prompt()set theforced_skillsprompt metadata (unless the caller already set it). If a local skill has the same name as a platform skill (case- and-/_-insensitive), both stay available and the local one is exposed asuser:<name>.
- BYOT: Fault-tolerant session recovery and isolation – Resilient MCP session recovery across server restarts (SSE, Streamable HTTP, stdio) in
sec_gemini.byot.session_guard. Re-establishes sessions automatically, enforces at-most-once semantics on tool replay (replaying onlyreadOnlyHint/idempotentHinttools), fails fast on hung HTTP connections via watchdog pings, isolates failing/hung servers during concurrentLIST_TOOLS,LIST_RESOURCES, andREAD_RESOURCEwith a 20s time box, and setsSSETransport.sse_read_timeoutto 1800s to support long-running tools.
Changed
Section titled “Changed”- Protobuf bindings moved to
sec_gemini_protos– The schema is now compiled exactly once, into a top-levelsec_gemini_protospackage that is vendored into the wheel.sec_gemini.protois a re-export facade, sofrom sec_gemini.proto import api_pb2keeps working unchanged. Dotted submodule imports such asimport sec_gemini.proto.api_pb2orfrom sec_gemini.proto.api_pb2 import ClientMessageno longer resolve; usefrom sec_gemini.proto import api_pb2(or importsec_gemini_protos.api_pb2directly) instead.
- BYOT/Tools: Fix BYOT interactions with network-attached storage (NAS/NFS) – Prevented
sec-gemini-byotevent-loop starvation, memory bloat, and tunnel disconnections when operating on slow network-attached storage (NAS/NFS) and large workspaces. Offloaded blocking workstation filesystem tools (read_file_by_lines,read_file_by_bytes,search_file_content,search_file,write_file,append_file,search_and_replace) to worker threads viaasyncio.to_thread(), skipped full-file SHA-256 hashing on files >50 MB, bounded subprocessstdout/stderrbuffering at 1 MB (MAX_OUTPUT_BYTES) while draining pipes to prevent deadlocks, surfaced explicit warnings whensearch_file_content/search_filehit size or entry limits, and added exponential-backoff auto-reconnect on registration timeout and transient registration EOF inByotService.
- Accounting Subsystem – Added accounting model for token usage, tool calls, and model cost estimation in
Sessionmodel. - Session Annotation – Annotated sessions with creation source (
web,tui,sdk). - DFIR Enhancements – Added
has_enrichmentparameter and total matches tosearch_logs, and enriched records count todescribe_tool. - Pyrefly Type Checker – Added Pyrefly type checking support to Python SDK and resolved all type suppressions.
- SDK/CLI: Wait for BYOT connection – CLI now waits for BYOT to connect when starting a session that requires it.
- SDK/Tests: CyberGym E2E test – Added CyberGym E2E integration test.
Changed
Section titled “Changed”- SDK: SecOps Backend Optimizations – Optimized SecOps backend queries to only include the minimum number of time buckets.
- BYOT: Proxied and corporate network support – BYOT now works in proxied environments and corporate networks with IPv6 filtering via native OS resolver defaults, automatic direct IPv4 fallback, and custom CA root bundle auto-discovery.
- SDK/Tools: Kill process groups on timeout – Subprocesses executed via
execute_commandnow run in a new process group and are fully killed on timeout, preventing resource leaks and GCS Fuse hangs. Suggests increasing timeout on exit status 137. - SDK: Fail-fast BYOT handshake – Made BYOT connection handshake timeout fail-fast to avoid long hangs.
- SDK/Proto: Reverted temporary concurrency fields – Reverted registration response concurrency fields to align with backend changes and fixed type checker errors.
- SDK: File pagination – Added support for
limitandpage_tokenparameters inSessionFiles.list(), returning aFileListcontainer with anext_page_token. - SDK/TUI/BYOT: Active environment logging – Enabled display and logging of the active environment (
dev,internal,public) in the SDK client, TUI status footer, and BYOT client.
- DFIR: Improved DFIR functionality. – Misc improvements.
- MCP: Safe process group termination – Sanitized process group killing (
killpg) to ensure targets are valid PIDs/PGIDs > 1, preventing the user session self-kill bug during unit test mocking.
- DFIR: User-defined LogStore – The enduser may now implement the search and describe log functions over their own infrastructure, without having to either convert to SQLite format or use a SecOps Chronicle instance.
- CLI:
dfirsubcommand – Addeddfirsubcommand with--sqliteand--chronicleoptions to automatically spin up logs MCP servers on dynamically allocated private ports in a background subprocess. - CLI: Non-interactive options – Added support for
--skilland--mcpflags in non-interactive CLI mode. - CLI/TUI:
--metaflag – Support passing arbitrary metadata options to sessions via the--metaflag. - TUI: Error metrics buttons – Added “Save Output” and “Save Trace” buttons on error messages in TUI.
- SDK: Connect RPC 2.1 upgrade – Upgraded RPC connections to support cursor streaming and caching.
- SDK: Skill resource unification – Unified local and remote skill access, parsing frontmatter YAML and exposing skills as standard resources.
- MCP: Modular environment and network workstation tools – Split the monolithic workstation tools into separate
environmentandnetworkMCP servers. - MCP: Log pagination – Added pagination and ordering parameters to the
describe_available_logstool. - BYOT: Concurrency and response chunking – Refactored the BYOT client to execute jobs concurrently and chunk large responses.
- BYOT: Observability and control enhancements – Added informative runner outputs, data masking, graceful Ctrl+C shutdown, and listing of connected BYOT clients and their tools in the Web UI.
- BYOT: Tunnel proxy support – Added tunnel proxy configurations and strict TCP reachability validation.
Changed
Section titled “Changed”- SDK: Standardized host override environment variables – Standardized environment variables for host overrides to
SEC_GEMINI_API_HOSTandSEC_GEMINI_BYOT_HUB_HOST. - SDK: Smarter session listing – Optimized session queries with a default 6-hour time window and a limit of 100 sessions.
- CLI: Switched message streaming mode – Changed CLI message streaming to improve output reliability and real-time visibility.
- BYOT: Standalone package deprecation – Deprecated the legacy standalone
sec-gemini-byotpackage, centralizing the BYOT client in the main SDK package.
- SDK: Enforced API key headers for file upload – Modified Python SDK to pass
sec-gemini-api-keyheader metadata onUploadFilegRPC calls. - SDK: Expired auth keys reporting – Improved error messages for expired keys across SDK and CLI components.
- SDK: Session expiration handling – Raise
SessionNotFoundErrorand terminate message streaming when session expires. - CLI/TUI: Config precedence – Resolved precedence issues between config files, CLI args, and environment variables when loading API keys.
- CLI: TUI startup error handling – Print TUI startup errors directly to console instead of exiting silently.
- CLI:
--mcpflag behavior – Only override session MCPs when the--mcpoption is explicitly provided. - TUI: Layout and text clipping – Fixed clipping, rendering order, and text wrapping issues on message feeds.
- TUI: Stream loop resiliency – Fixed streaming recovery after
stream_read_errorand session creation race conditions. - TUI: Deferred/lazy session creation – Fixed rendering and state bugs during deferred session creation.
- BYOT: Resource leaks and event loop blocking – Fixed BYOT background task leaks, keepalive ping intervals, and event loop blocks on reconnection.
- BYOT: Connection hangs – Resolved connection hangs in tool fetcher.
- MCP: SecOps backend bugfix – Fixed an issue in the SecOps MCP server where calling log search functions raised a
"cannot pickle '_thread.RLock' object"error. - Moved DFIR tools to BYOT binary – Fixed an issue where Sec-Gemini-MCP tools were being loaded for DFIR workflows.
- CLI:
--versionflag – Added--versionflag to the mainsec-geminicommand to print the version frompyproject.toml.
– CLI: -p / --prompt option – Run Sec-Gemini in non-interactive mode.
– CLI: --output option – Useful to write the results to a file when in non-interactive mode.
-
TUI: skills panel in right sidebar – Loaded skills now appear in a dedicated “skills” section in the right panel (between tasks and top tools), showing skill name, origin (sec-gemini/byot), and description. Skills no longer clutter the chat feed.
-
BYOT:
--skillCLI flag – Added support for loading local skill files (.md) in the standalone BYOT CLI. Skills are exposed as MCP resources, allowing the cloud agent to discover and use them. Mirroring existingBackend.start_byotfunctionality. -
TUI: renamed
sec-gemini2tosec-gemini– The main CLI and terminal UI are now accessible via the shortersec-geminicommand. -
TUI: add fast mode – Add the ability to select “fast mode” at session creation time in the TUI, which makes SecGemini use a faster harness.
-
BYOT: integrated into
sec-geminipackage – The Bring Your Own Tool client is now part of the core SDK and available viasec-gemini-byot. -
Server: proper SKILL_LOADED messages – Improved display of loaded skills in the message stream, reducing clutter.
-
MCP:
list_session_mcp_serversnow includes skills – The response was previously missing theskillsarray from MCP server info.
Changed
Section titled “Changed”- CLI: extracted from TUI – Moved
cli.pyandcommands/directory fromsec_gemini/tui2to a newsec_gemini/clipackage. The main entry pointsec-gemininow points tosec_gemini.cli.cli:cli. - CLI: cleaner
--modehandling – Updated--modeto useclick.Choice(["dfir"])withNonedefault, mapping to""internally for cleaner help output. - CLI: updated help text – Removed “TUI v2” from the main help description to reflect that it is now the main CLI.
Removed
Section titled “Removed”- CLI: stub subcommands – Removed
modelandsessionssubcommands as they were stubs. - CLI:
--skillsalias – Removed--skillsalias, leaving only--skill.
-
Centralized logging module – Moved
sec_gemini/tui2/logging.pytosec_gemini/logging.pyso all components (TUI, MCP server, BYOT CLI) share the same structured JSON logging infrastructure. Fixed_KwargsAdapterto store structured fields safely, avoidingLogRecordattribute collisions (e.g.name=). -
BYOT:
setup_byot_logging()– New convenience function for the standalone BYOT CLI. Writes rotating JSON to~/.config/sec-gemini/logs/byot.logplus colored console output via Rich. Added--verboseCLI flag. -
BYOT: dedicated log file – MCP server now writes BYOT logs to a separate
byot.logvia a namespace handler onsecgemini.byot, in addition tomcp.logvia the root logger. -
MCP: BYOT observability tools – Added 3 new Layer 1 tools:
get_byot_status(state, tools, hub URL, uptime, errors),list_byot_tools(focused tool listing),reload_byot(stop + restart with refreshed config). Added 2 debug tools:byot_logandbyot_log_grepfor inspecting BYOT logs. -
MCP:
mcp_reloadsendsToolListChangedNotification– After re-registering tools, the client is notified so it re-fetches the tool list. New tools appear immediately without a server reconnect. -
MCP:
mcp_reloadcovers BYOT and tools modules – Addedsec_gemini.byot.*andsec_gemini.tools.*to the reload list so BYOT code changes take effect without restarting the MCP server. -
BYOT: structured logging – Converted
byot/service.pyandbyot/client.pyto useget_logger()with structured kwargs (tool_count=,hub_url=,job_id=) instead of%sformatting. -
BYOT: better auth error reporting – Hub registration rejection now logs
registration_rejectedwith hub URL and key prefix, and raises a more descriptive error message. -
MCP: TUI lifecycle tools – Added
tui_start,tui_stop,tui_statusdebug tools that launch/manage the TUI as a headless subprocess. Enables autonomous TUI debugging from Claude Code without manual terminal setup. -
TUI: debug socket server – New
DebugServerintui2/debug_server.pyexposes a Unix domain socket (~/.config/sec-gemini/debug.sock) when--debugis passed. Accepts JSON commands for screen inspection, widget queries, clicks, keypresses, and state dumps. -
TUI:
--debugand--headlessCLI flags –sec-gemini run --debugstarts the debug socket server;--headlessruns without a terminal for MCP-managed sessions. -
sec_gemini/backoff.py–ExponentialBackoffutility with full jitter for use in reconnection and retry logic. -
30 new unit tests covering dispatch routing, error handling, reconnection backoff, retry behavior, and session state management.
-
TUI: stream loop stops after terminal state – The message stream loop no longer re-subscribes every 30s after a session reaches COMPLETED, FAILED, CANCELED, or MAX_ATTEMPTS_EXCEEDED. Previously this caused the server to replay the entire message history indefinitely. The session VM now tracks status changes via a callback and sets COMPLETED on AGENT_IS_DONE receipt.
-
BYOT: idempotent start –
start_byot()returns current tools when BYOT is already running instead of raising an error. Fixes the “BYOT already created” toast when creating a second session. -
BYOT: hot-reload resilience – MCP status tools (
get_byot_status,list_byot_tools) access raw service attributes to survive Pydantic class identity mismatches aftermcp_reload().ByotService.status()also converts tools to dicts before constructingByotStatus. -
Sessions: sorted newest-first –
list_sessions()now returns sessions sorted bycreated_atdescending in both the Backend and MCP tool layer. -
MCP:
mcp_reloadnow re-registers tools – Previously only reloaded modules without updating the registered tool closures. Now callsregister_all_tools()andregister_debug_tools()after reload so code changes take effect without restarting the MCP server. -
MCP: TUI inspection tools use IPC –
tui_screenshot,tui_get_screen,tui_query,tui_click,tui_type,tui_press,tui_get_statenow communicate via the debug Unix socket instead of requiring an in-process app reference that was never set in standalone mode. -
MCP: stale debug socket cleanup –
tui_stopand MCP lifespan shutdown now remove the debug socket file to prevent stale socket issues. -
Session:
get()reuses cached sessions –ClientSessions.get()now returns the existing tracked session instead of always creating a fresh one, which was clobbering accumulated state (status, name, created_at). -
Session: server-assigned names applied from stream – Added
Session.handle_streamed_message()to pick upMESSAGE_TYPE_SESSION_NAMEfrom server.SessionMessagesnow holds a reference to its parentSessionand calls the handler before yielding messages. -
Session: state reconciliation after reconnection – Added reconnect callback mechanism to
RpcClient.ClientSessionsregisters_reconcile_stateat bind time, callinglist()after reconnection to resync all session state from the server. -
Connection: improved message routing reliability – Message routing now uses strict request ID matching, ensuring reliable delivery and preventing misrouting or silent drops.
-
Connection: exponential backoff on reconnection – Replaced fixed 0.2s/1.0s reconnection delays with exponential backoff using full jitter (base=0.5s, max=30s, multiplier=2x). Prevents connection storms and server-side rate limiting during network instability.
-
Session: log warning on invalid status –
update_from_eventnow logs a warning when it receives an unrecognized status string, instead of silently swallowing theValueError. -
Session: handle name and created_at from events –
update_from_eventnow updates_nameand_created_atwhen those fields are present in the event dict. -
ClientSessions: handle session_not_found –
_handle_server_messagenow handlessession_not_foundevents by removing stale sessions from the local cache and logging a warning. -
ClientSessions: log unknown session state changes – State change events for sessions not in the local registry now emit a debug log instead of being silently ignored.