Netclaw 0.16.0
0.16.0 2026-04-27
Netclaw v0.16.0 — Discord session continuity, public audience hardening, reminder expiration, and init wizard overhaul
Features
Added reminder expiration, self-cancellation guidance, and delivery timeout fix — recurring reminders now support an optional
ExpiresInparameter onset_reminder(also available as--expires-inin the CLI and REST API) that automatically disables the reminder after the specified duration. Recurring reminder prompts now include self-cancellation guidance telling the agent to callcancel_reminderwhen the task's purpose is permanently fulfilled (e.g., PR merged, deploy completed).DeliveryObservedTimeoutis aligned withExecutionTimeoutSeconds(300s) so delivery-required reminders are no longer marked as failed when the LLM turn legitimately takes longer than 30 seconds to complete. (#752)Added public audience security hardening — Public sessions are now fully amnesic (no memory read or write access by default), the startup tool index is filtered by effective audience so Public sessions do not see capabilities they cannot use, and the system prompt is rebuilt on the first inbound turn once the resolved channel audience is known. File-access denials no longer include root path hints for public sessions. Closes #755, #756. (#758)
Added Discord approval button clearing after decision — Discord approval prompt messages are now updated in-place after a user clicks an approval button or types a text response (A/B/C/D), replacing the buttons with a resolved status showing the tool name, action, decision, and who approved. This matches the existing Slack behavior. (#768)
Added configuration-driven channel statistics —
netclaw statsandnetclaw statusnow only display channel panels for channels that are actually enabled in configuration. A Discord-only deployment no longer shows an empty Slack section, and the underlying telemetry registry is now extensible per channel type viaChannelTelemetry.For(ChannelType). Closes #773. (#774)Streamed attachment downloads to disk instead of buffering in memory — attachment downloads from Slack and Discord no longer buffer entire files in managed heap memory. A shared
StreamingAttachmentDownloaderstreams HTTP responses directly to a temp file using a pooled 81 KB buffer and enforces the operator-configuredMaxFileBytesceiling mid-stream via Content-Length header check and byte-counting fallback. Content scanning reads only the first 64 bytes from disk. Closes #757. (#770)Added unified channel picker step for the init wizard — the
netclaw initwizard now presents a single "Communication Channels" checklist step replacing the previous sequential Slack (step 3) and Discord (step 4) steps. Users navigate with↑/↓, toggle channels withSpace, configure withEnter, and advance with[d]. Adding additional channel adapters in the future only requires implementingIChannelAdapterViewModel. Closes #742. (#763)Resolved Discord channel IDs to human-readable names in the init wizard — Discord channel entries in the Channels wizard step now display as
"GuildName / #channelName"instead of raw snowflake IDs. Channel resolution runs as a background task while the user completes other sub-steps, adding no blocking delay. Closes #743. (#762)Made
AllowedUserIdsan explicit allow/restrict choice in the init wizard — the plain textAllowedUserIdsinput in both Discord and Slack wizard steps is replaced with a two-phase flow: an explicit binary selection ("Restrict to specific users" vs "Allow anyone in allowed channels"), then conditionally a mandatory user ID text input. This prevents accidental open access from pressing Enter on a blank field, enforcing the default-deny security posture. Closes #760. (#778)Disabled
System.Objectserialization fallback —WithNetclawSerialization()now callsWithStrictSerialization()to disable the JSON fallback for unregistered types. Unregistered types now throw aSerializationExceptioninstead of silently producing JSON output, making serialization misconfigurations immediately visible. Closes #706. (#777)Blocked self-update in container deployments and hardened NSec initialization — a new
Daemon.DisableSelfUpdateconfig option (automatically set totruein the official Docker image viaNETCLAW_Daemon__DisableSelfUpdate=true) blocksnetclaw updatefrom replacing binaries in-place while keeping update availability checks running so operators know when a new image is available. All update notifications when self-update is disabled now advise pulling a newer container image instead. Also addedlibsodium23to the Dockerfile so NSec Ed25519 signature verification works correctly in Ubuntu 24.04 self-contained containers, and hardenedMinisignVerifier.Verify()to catch NSec platform initialization failures and returnPlatformUnavailableinstead of throwing. Closes #771, #772. (#776)
Bug Fixes
Fixed Discord thread sessions dropping messages after daemon restart — after a daemon restart, messages sent to an existing Discord thread were silently dropped unless the user @mentioned the bot again, because the in-memory session binding actor was lost and
threadExistswas false, matching theChannelMentionRequiredrouting policy path.DiscordRoutingPolicynow returnsStartOrContinuefor in-thread messages regardless of whether a binding actor exists, matching the existing Slack behavior and allowing Akka Persistence to recover prior session state seamlessly. (#779)Fixed dead
OwnerIdentitysub-step appearing in Slack init wizard — a no-longer-neededOwnerIdentitysub-step was still included in the Slack wizard's step sequence, causing an extra blank step to appear duringnetclaw init. Closes #761. (#764)