All notable changes to OpenCrab will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
- Config hot-reload via
watchchannel — Replaced per-channelMutexcopies of config (allowlists, voice, respond_to, idle_timeout) with a singletokio::sync::watch<Config>channel. All channels now read the latest config per-message from the watch receiver. Removedallowed_users/allowed_phonesHashSet fields from all channel states and 4 separate allowlist callbacks inui.rssrc/channels/factory.rs,src/channels/{telegram,discord,slack,whatsapp}/{mod,agent,handler}.rs,src/cli/ui.rs,src/brain/tools/{telegram,discord,slack,whatsapp}_connect.rs,src/brain/tools/whatsapp_send.rs
- TTS voice/model read from
[providers.tts]— Addedvoiceandmodelfields toTtsProviderssovoice = "echo"under[providers.tts]is actually picked up. Previously serde silently ignored the fieldsrc/config/types.rs,src/channels/factory.rs,src/channels/{telegram,discord,slack,whatsapp}/handler.rs
- Default TTS voice changed from "ash" to "echo"; both
stt_enabledandtts_enablednow default tofalse(user must opt in)src/config/types.rs
- Telegram "Session not found" after TUI quit — The retry logic checked for
"SessionNotFound"(camelCase) but the error Display produces"Session not found"(lowercase), so recovery never triggered. Now correctly matches and creates a fresh session (closes #24)src/channels/telegram/handler.rs
- Duplicate data delivery on Telegram — LLM sent data both as streaming text response AND via
telegram_send, resulting in the same content appearing twice. Added channel context prefix to all handlers telling the LLM its text response is auto-delivered (closes #23)src/channels/{telegram,discord,slack,whatsapp}/handler.rs
- Groq API key in test fixture — Replaced real-format Groq key in
redact_secretstest with obviously fake placeholder (closes #25)src/utils/sanitize.rs
0.2.49 - 2026-03-04
- Channel commands (
/help,/usage,/models,/stop) — All four commands now work on Telegram, Discord, Slack, and WhatsApp. Sharedcommands.rsmodule handles parsing; each channel renders platform-native responses (inline keyboards, action rows, Block Kit buttons)src/channels/commands.rs(new),src/channels/mod.rs,src/channels/telegram/handler.rs,src/channels/discord/handler.rs,src/channels/slack/handler.rs,src/channels/whatsapp/handler.rs
/stopcancels running agent on channels —CancellationTokenper session, equivalent to double-Escape in TUI. Immediately aborts streaming/tool loop mid-runsrc/channels/telegram/mod.rs,src/channels/discord/mod.rs,src/channels/slack/mod.rs,src/channels/whatsapp/mod.rs, all handler files
/modelsinteractive model switching on channels — Platform-native buttons (TelegramInlineKeyboardMarkup, DiscordActionRow, Slack Block Kit) withmodel:callback handlerssrc/channels/telegram/agent.rs,src/channels/discord/agent.rs,src/channels/slack/handler.rs
- Agent
slash_commandtool returns real data —/models,/usage,/help,/doctor,/sessionsnow execute and return actual context instead of "TUI-only" errors, enabling the agent to read config, check health, and switch models viaconfig_managersrc/brain/tools/slash_command.rs,src/brain/tools/trait.rs,src/brain/agent/service/tool_loop.rs
service_contextonToolExecutionContext— Tools can now accessServiceContextfor DB queries (used by/usageand/sessions)
- Image API key stored under wrong path — Onboarding wrote to flat
[image]section in keys.toml instead of[providers.image.gemini], inconsistent with all other provider keys. AddedImageProvidersstruct, merge logic, and legacy fallbacksrc/config/types.rs,src/tui/onboarding/config.rs
- Channel commands section in README — Documented
/help,/usage,/models,/stopfor all channels including WhatsApp keys.tomlparse errors now surface visibly — Invalid TOML (e.g. unquoted emails) previously caused silent key merge failure, breaking provider startup with no error. Now prints warning to stderr and logs error./doctorvalidates keys.toml syntaxsrc/config/types.rs,src/brain/provider/factory.rs,src/brain/tools/slash_command.rs
- Telegram tool calls as individual messages — Each tool call now gets its own message (context + result) instead of all tools stacked in the response. Response streams cleanly at the bottom
src/channels/telegram/handler.rs
- Intermediate agent texts visible on Telegram — Agent commentary between tool rounds (e.g. "Found one! Let me reply to this:") now appears as individual messages, matching TUI behavior
src/channels/telegram/handler.rs
0.2.48 - 2026-03-04
- Telegram thinking/reasoning stream — Live
💭reasoning content streams during inference, vanishes on tool calls and response chunks, keeping the conversation cleansrc/channels/telegram/handler.rs
quick_jumpmode for/onboard:<step>deep-links — Any/onboard:step(except ModeSelect) opens locked to that single step: no progress dots, centered title, Enter confirms, Esc exits to chat. Step-change detection reverts navigation attemptssrc/tui/onboarding/wizard.rs,src/tui/onboarding/input.rs,src/tui/app/messaging.rs,src/tui/onboarding_render.rs
- Deferred health re-check on Enter — In
/doctorquick_jump mode, Enter resets all checks to Pending (visible flash), tick resolves them next frame. Reloads config from disk so external changes are picked upsrc/tui/onboarding/config.rs,src/tui/onboarding/fetch.rs,src/tui/app/state.rs
- YOLO (permanent) approval button on all channels — Telegram, Discord, Slack, and WhatsApp now offer a 🔥 YOLO button alongside Always (session), persisting
auto-alwaysto config.toml so approval survives restartssrc/channels/telegram/handler.rs,src/channels/telegram/agent.rs,src/channels/discord/handler.rs,src/channels/discord/agent.rs,src/channels/slack/handler.rs,src/channels/whatsapp/handler.rs,src/channels/whatsapp/mod.rs,src/utils/approval.rs,src/utils/mod.rs
- Redundant
check_approval_policy()in tool loop — Removed config-level short-circuit that was bypassing per-tool approval logic, fixing 3 approval policy test failures on CIsrc/brain/agent/service/tool_loop.rs
- CI and Release workflows running redundantly on tag push — Added
tags-ignore: v*to CI, added test gate (needs: test) to Release workflow.github/workflows/ci.yml,.github/workflows/release.yml
/doctorstandalone mode (closes #21) — No onboarding chrome, Enter/Esc exit, removed redundant/onboard:healthcommandsrc/tui/onboarding_render.rs,src/tui/app/state.rs,src/tui/render/help.rs
- Trello API Token not loaded in
from_config()— Health check falsely reported "No API Token provided" even when configuredsrc/tui/onboarding/wizard.rs
- Model selector filter not working (closes #20) — Filter text was typed but never applied to the displayed model list
src/tui/render/dialogs.rs
- UTF-8 crash on multi-byte text in all channels — 12 unsafe byte-index string slices replaced with
truncate_str(), fixing panic on accented/emoji characters (e.g. Portugueseõ)src/channels/telegram/handler.rs,src/channels/discord/handler.rs,src/channels/slack/handler.rs,src/channels/whatsapp/handler.rs
quick_jumpblocking all step navigation — Guard was catching internal step changes (field switching, channel sub-steps), not just step completion. Moved guard intonext_step()so only step completion exits in deep-link modesrc/tui/onboarding/input.rs,src/tui/onboarding/navigation.rs,src/tui/onboarding/wizard.rs
- Approval policy not persisting from channels — Channels only offered "Always (session)" which wrote
auto-session, downgrading the default YOLO policy. Now properly offers both session and permanent options - Updated README and commands.toml.example with all
/onboard:*sub-commands,/doctor,/whisperREADME.md,commands.toml.example
0.2.47 - 2026-03-03
- Centralized tool approval into shared
utils::approvalmodule — Replaced per-channelauto_approve_session: Mutex<bool>fields in Discord, Slack, Telegram, and WhatsApp with a single config-driven source of truth. Two new functions (check_approval_policy,persist_auto_session_policy) read/writeconfig.tomldirectly, and the coretool_loop.rschecks policy first before delegating to any channel callback. Approval callbacks moved frommod.rstohandler.rsas free functions across all channelssrc/utils/approval.rs(new),src/utils/mod.rs,src/brain/agent/service/tool_loop.rs,src/channels/discord/mod.rs,src/channels/discord/handler.rs,src/channels/slack/mod.rs,src/channels/slack/handler.rs,src/channels/telegram/mod.rs,src/channels/telegram/handler.rs,src/channels/whatsapp/mod.rs,src/channels/whatsapp/handler.rs,src/channels/trello/handler.rs
- Telegram streaming message stuck at top between tool calls — Streaming now uses separate
toolsandresponsefields with arecreateflag that deletes the old message and creates a fresh one below the approval buttons after each tool completion, so the conversation flows naturally downward instead of getting stuck above approval messages. Thanks @opryshok for reporting #17 and #16 — your bug reports directly drove this fix and the v0.2.46 improvementssrc/channels/telegram/handler.rs,src/channels/telegram/agent.rs
- Race condition in approval registration across all channels — Pending approval is now registered BEFORE sending the approval message (not after), preventing a window where the user could click before the handler was ready
src/channels/discord/handler.rs,src/channels/slack/handler.rs,src/channels/telegram/handler.rs
- TUI "Always" approval choice not persisting — Clicking "AllowAlways" in the TUI now writes
approval_policy = "auto-session"toconfig.tomlso the choice survives restarts and is respected by all channelssrc/tui/app/input.rs,src/tui/app/messaging.rs,src/tui/app/state.rs
- Tracing/logging across all channel approval flows — Every approval request, response, and edge case now logs via
tracing::info!/tracing::warn!for easier debuggingsrc/channels/discord/agent.rs,src/channels/discord/handler.rs,src/channels/slack/handler.rs,src/channels/telegram/agent.rs,src/channels/telegram/handler.rs,src/channels/whatsapp/handler.rs
- Cross-channel approval awareness — TUI reads approval policy from
config.tomlon session create/load, so a policy set via Telegram or any other channel is picked up everywheresrc/tui/app/messaging.rs,src/tui/app/state.rs
0.2.46 - 2026-03-03
- Telegram tool approval stuck after clicking Yes/Always (
3716bf9) — Three root causes fixed: (1)ApprovalCallbacknow returns(bool, bool)where the second bool propagates "Always" back intotool_context.auto_approve, so it persists across the entire tool loop instead of resetting after a few steps. (2) Race condition: pending approval is registered BEFORE sending the message, not after. (3) Tool input truncated to 3500 chars to prevent silent Telegram API rejection on long inputs. Closes #17src/brain/agent/service/types.rs,src/brain/agent/service/tool_loop.rs,src/channels/telegram/mod.rs,src/channels/discord/mod.rs,src/channels/slack/mod.rs,src/channels/whatsapp/handler.rs,src/tui/app/state.rs,src/cli/ui.rs
- Telegram missing tool call context and formatting (
3716bf9) —ToolCompletedevents were being dropped by the progress callback; tool indicators used unsupported markdown. Now shows tool start/completion with proper labels. Improvedmarkdown_to_telegram_htmlwith headers, links, lists, underscore italic, and strikethrough. Closes #16src/channels/telegram/handler.rs
- Multiline Up/Down arrow keys never navigated lines (
e27f59b) — The multiline branch consumed all Up/Down events when the buffer contained newlines, even at boundaries (cursor at position 0 or end), blocking fall-through to history navigation. Now yields at boundaries: Up at position 0 falls through to history, Down at end of buffer does nothingsrc/tui/app/input.rs
- Light mode unreadable — user messages and UI text invisible on light terminals (
009e8e3) — Removed hardcoded dark user message backgroundRgb(30,30,38). ReplacedColor::White(invisible on light backgrounds) withColor::Reset(terminal's default foreground) across all render files. Diff backgrounds changed from dark RGB to ANSI named colors (Green/Red/DarkGray) that adapt to both themessrc/tui/render/chat.rs,src/tui/render/input.rs,src/tui/render/help.rs,src/tui/render/dialogs.rs,src/tui/render/sessions.rs,src/tui/render/tools.rs
- Streaming token count duplicated ctx counter in input bar (
2f8bc09) — The per-chunk tiktoken counter was addingctx + outputtogether and feeding it back intolast_input_tokens, making the tool group display show the same "28K ctx" already in the input bar, plus a duplicate timer. Now output tokens are tracked separately and displayed as a per-response count next to the timer:(7s · 42 tok). The duplicate ctx+timer block below tool groups is removedsrc/tui/events.rs,src/tui/app/state.rs,src/tui/app/messaging.rs,src/tui/render/chat.rs,src/cli/ui.rs
- Removed auto-backup logic (
e142698) — Git handles versioning; the custom backup mechanism was redundant
0.2.45 - 2026-03-03
- Real-time token count during streaming (
65a0278) — The context usage display in the input box now increments live as the model responds: each streaming chunk is counted via tiktoken (cl100k_base) and fires aTokenCountUpdatedevent, so the counter ticks up token by token (e.g.45K → 45.1K → 45.3K) instead of jumping at the end of each API round-trip. The API-reported real count resets the baseline after each response, keeping the display accurate across multi-tool loopssrc/cli/ui.rs
- Elapsed time + ctx in thinking indicator (
65a0278) — The "OpenCrabs is thinking..." spinner now shows elapsed seconds and current context size:⠙ OpenCrabs is thinking... 3s · 45K ctxsrc/tui/render/mod.rs
- Running token count below active tool groups (
65a0278) — While tool calls execute, a subtle45K ctx · 3sline is rendered below the live tool group so you can see context growth during multi-tool sequencessrc/tui/render/chat.rs
opencrabs daemoncommand (be61993) — New headless subcommand: same full channel setup (Telegram, Discord, Slack, WhatsApp) as the TUI, but no terminal UI. Blocks on Ctrl-C. Designed for use by the systemd/LaunchAgent service installed during onboarding. Fixes the daemon not working afteropencrabs init(issue #12)src/cli/mod.rs,src/cli/ui.rs
- 28 CLI parsing unit tests (
be61993) — Full test coverage for all CLI subcommands including the newdaemoncommand. Wired intolib.rsunder#[cfg(test)]src/tests/cli_test.rs,src/tests/mod.rs,src/lib.rs
- Hot-reload for all three config files (
1675fd2) —config_watchernow watchesconfig.toml,keys.toml, andcommands.toml. Changing any of them is picked up within ~300ms without restart. Provider is swapped live when keys change (viaAgentService::swap_provider). TUI refreshes approval policy and slash commands on reloadsrc/utils/config_watcher.rs,src/cli/ui.rs,src/tui/app/state.rs
config.tomlandcommands.tomlannotated examples (4fdc1a6) — Full annotatedconfig.tomlexample added to the README Configuration section. Newcommands.tomlsection with complete syntax and action types reference. Newcommands.toml.examplefile in the project root matching the style ofkeys.toml.example. Two new Table of Contents entries addedREADME.md,commands.toml.example(new)
- Daemon service not starting after install (
be61993) — systemdExecStartwas missing thedaemonsubcommand arg andsystemctl --user startwas never called after enable. macOS LaunchAgent plist was also missing thedaemonarg inProgramArguments. Both fixed. Closes #12src/tui/onboarding/config.rs
- config_watcher test hanging the test runner (
be61993) — Blockingrx.recv()loop insidespawn_blockingkept the tokio runtime from shutting down after tests. Fixed with a 200ms-poll loop and hard 3s deadline so the blocking thread exits cleanlysrc/utils/config_watcher.rs
- Nightly rustfmt CI failures (
3208ac7) —telegram/mod.rsandwhatsapp/handler.rshad formatting differences between local stablerustfmtand the nightly toolchain used by CI. Fixed by runningcargo fmtthrough the pinned nightly toolchain fromrust-toolchain.tomlsrc/channels/telegram/mod.rs,src/channels/whatsapp/handler.rs
- Redundant
.max(0)on usize aftersaturating_sub(00fc64d) — Clippyunnecessary_min_or_maxlint:usize::saturating_sub(1)already clamps at 0,.max(0)was always a no-op. Removed from three fields in onboarding channelssrc/tui/onboarding/channels.rs
- llama-cpp-2 Metal segfault on macOS 26 arm64 (
118ea65) — Bumpedllama-cpp-2from0.1.134to0.1.137which includes the upstream Metal fix. Thanks @Pibomeister (PR #13)Cargo.toml,Cargo.lock
- Default approval policy changed to
auto-alwaysfor new users (3ed02ef) — New installations no longer prompt before every tool call. The agent works autonomously out of the box. Existing users withapproval_policyset inconfig.tomlare unaffected (serdedefaultonly applies when the field is absent). To opt back into per-call prompts: run/approve→ "Approve-only (always ask)"src/config/types.rs,README.md
- Telegram allowlist hot-reload extended to Discord and Slack (
2b9b8c6,bd95b52) —allowed_userslists for all three text channels now update at runtime whenconfig.tomlchanges, without restart. Builds on the allowlist hot-reload foundation contributed by @Pibomeister (PR #14)src/channels/telegram/mod.rs,src/channels/discord/handler.rs,src/channels/slack/handler.rs,src/utils/config_watcher.rs
0.2.44 - 2026-03-02
- Google Gemini provider (
e715536) — FullProvidertrait implementation against the Gemini REST API (generativelanguage.googleapis.com/v1beta). Streaming via SSE, tool use withfunctionDeclarations/functionCall/functionResponse, vision (multimodalinlineData), 1M–2M token context window. Live model list fetched from the Gemini API during onboarding and/models. Auth via?key=query paramsrc/brain/provider/gemini.rs(new),src/brain/provider/factory.rs,src/brain/provider/mod.rs
- Image generation & vision tools (
e715536) — Two new agent tools powered bygemini-3.1-flash-image-preview("Nano Banana"), independent of the main chat provider:generate_image— Generate an image from a text prompt; saves PNG to~/.opencrabs/images/; returns file path for channel deliveryanalyze_image— Analyze an image file path or URL via Gemini vision; works even when the main model doesn't support visionsrc/brain/tools/generate_image.rs(new),src/brain/tools/analyze_image.rs(new),src/brain/tools/mod.rs
- ImageSetup onboarding step (
e715536,1336b89,f534b24) — Step 7 in Advanced mode (after VoiceSetup, before Daemon). Toggle Vision Analysis and Image Generation independently; API key input with mask/replace mode; existing key detection. Model labeled asgemini-3.1-flash-image-preview (🍌 Nano Banana). Persistent "get a free key at aistudio.google.com" hint shown when no key is set. Navigation: Space/↑↓ to toggle, Tab/Enter to continue, BackTab/Esc to go backsrc/tui/onboarding/types.rs,src/tui/onboarding/wizard.rs,src/tui/onboarding/navigation.rs,src/tui/onboarding/fetch.rs,src/tui/onboarding/config.rs,src/tui/onboarding_render.rs
/onboard:imagedeep-link (e715536) — Jump directly to the ImageSetup step from chat at any timesrc/tui/app/messaging.rs
- On-demand brain file loading (
3224048) —build_core_brain()replacesbuild_system_brain()at startup — injects only SOUL.md + IDENTITY.md (~1-2k tokens). All other brain files listed in a memory index; loaded by the agent viaload_brain_file(name)tool on demand.name="all"loads everything. Dramatically reduces baseline token overhead for every messagesrc/brain/prompt_builder.rs,src/brain/tools/load_brain_file.rs(new),src/cli/ui.rs
write_opencrabs_filetool (8f3d648) — Writes any file inside~/.opencrabs/(brain files, config, keys). Replaces the broken agent pattern of usingedit_file/write_filewhich are locked to the working directory byvalidate_path_safety()src/brain/tools/write_opencrabs_file.rs(new),src/brain/tools/mod.rs
respond_toselector in Telegram/Discord/Slack onboarding (9ecc8f0) — New field in each channel's setup step; chooseall/dm_only/mentionmode during onboarding instead of editing config.toml manuallysrc/tui/onboarding/types.rs,src/tui/onboarding/fetch.rs,src/tui/onboarding_render.rs,src/tui/onboarding/config.rs
- Google Image API Key in health check (
6923174) — When image features are enabled, the health check step verifies the Google AI key is presentsrc/tui/onboarding/config.rs
send_fileaction — discord_send and slack_send (905e9ef) — New action uploads a local file as a native attachment. Discord: file attachment in channel. Slack: file upload via API. Both tools now at 17 actionssrc/brain/tools/discord_send.rs,src/brain/tools/slack_send.rs
add_attachmentaction — trello_send (ac44fc3) — New action uploads a local image or file as a Trello card attachment via multipart upload; returns the hosted Trello URL. Tool now at 22 actionssrc/brain/tools/trello_send.rs,src/channels/trello/client.rs
- Full file/image/audio input pipeline across all channels (
9aed2ea,5bc33f5) — Unifiedclassify_file(bytes, mime, filename) → FileContentutility routes incoming files across every channel: images → vision pipeline (<<IMG:path>>), text/code/data files → extracted inline (up to 8 000 chars), audio → STT, PDFs → note to paste or useanalyze_image. Trello: card attachments are fetched and processed on every incoming comment. Slack: voice/STT support added (was missing). All channels now handle images, text files, documents, and audio with consistent behaviorsrc/utils/file_extract.rs(new),src/utils/mod.rs,src/channels/telegram/handler.rs,src/channels/discord/handler.rs,src/channels/whatsapp/handler.rs,src/channels/slack/handler.rs,src/channels/slack/agent.rs,src/brain/tools/slack_connect.rs,src/channels/trello/client.rs,src/channels/trello/handler.rs,src/channels/trello/models.rs
- TUI text file input (
3e4460e) — Paste or type any text file path in the TUI input field — the file is read and inlined automatically as[File: name]\n```\ncontent\n```. Works at paste time and submit time. Supports.txt,.md,.json,.yaml,.toml,.rs,.py,.go,.sql, and 20+ other formatssrc/tui/app/state.rs,src/tui/app/messaging.rs
- Generated images delivered as native media across all channels (
60584ff) —<<IMG:path>>markers in agent replies are now unwrapped and delivered natively on every channel: Telegramsend_photo, WhatsApp image message, Discord file attachment, Slack file upload, Trello card attachment +embed in comment. Previously the raw marker string was sent as plain textsrc/channels/telegram/handler.rs,src/channels/discord/handler.rs,src/channels/whatsapp/handler.rs,src/channels/slack/handler.rs,src/channels/trello/handler.rs
- Trello outgoing images — upload attachment + embed inline (
3e4460e) — Agent replies containing<<IMG:path>>on Trello are now uploaded as card attachments viaadd_attachment_to_cardand embedded in the comment as. Previously the marker was silently droppedsrc/channels/trello/handler.rs
- Channel tool approval + TUI real-time updates follow-up (
248b719) — Follow-up fixes to tool approval flows and TUI live-update reliability across all remote channels after the v0.2.43 multi-channel expansionsrc/channels/*/mod.rs,src/brain/agent/service/tool_loop.rs,src/tui/app/state.rs
- Clippy: collapse nested if blocks (
2595550) — Fixed twocollapsible_iflint errors inmessaging.rs(TUI text file detection) andwhatsapp/handler.rs(document attachment handling)src/tui/app/messaging.rs,src/channels/whatsapp/handler.rs
- TUI silent message queue after errors (
dc815ce) — After any agent error,processing_sessionswas never cleared for the current session, causing all subsequentsend_messagecalls to be silently queued with no agent running. Fixed by unconditionally removing the session fromprocessing_sessionsandsession_cancel_tokensin theTuiEvent::Errorhandler before branching on current vs background sessionsrc/tui/app/state.rs
- TUI real-time updates during channel tool loops (
b44f1ff) — Remote channel tool loops (Telegram, WhatsApp, etc.) were not firingsession_updated_txon each chunk, causing the TUI to only refresh at the end of a long tool sequence. Now fires after every tool call completionsrc/brain/agent/service/tool_loop.rs
- Attachment input shows "Image #N" instead of full path (
2609583) — Attachment display in the TUI input bar was showing the full file path; now showsImage #N,Document #Nplaceholders matching the<<IMG:...>>/<<DOC:...>>injection formatsrc/tui/render/input.rs
- WhatsApp TTS — upload media before sending audio message (
135b4d6) — TTS audio was being sent viasend_audiobefore uploading to WhatsApp media servers, causing delivery failures. Now uploads first, then sends with the returned media IDsrc/channels/whatsapp/handler.rs
- WhatsApp handler regression — empty
allowed_phones+ connect tool (5a32d49) — Emptyallowed_phonesin config was incorrectly blocking all messages including the owner.whatsapp_connecttool now correctly writes the config entry. Owner bypass re-validatedsrc/channels/whatsapp/handler.rs,src/brain/tools/whatsapp_connect.rs
- WhatsApp security — block owner→contact processing (
0fc8b2e) — Messages sent by the owner to a contact were being processed as if the contact sent them, exposing the agent to arbitrary tool execution from outgoing messagessrc/channels/whatsapp/handler.rs
- WhatsApp outgoing
allowed_usersenforcement (1707e0f) — Outgoing messages to contacts not inallowed_userswere being processed; now strictly gatedsrc/channels/whatsapp/handler.rs
- Context display reset immediately after compaction (
2c4ca8e) — After/compact, the context percentage in the TUI header was not resetting to the new value until the next message; now resets immediatelysrc/tui/app/state.rs
- Per-channel config structs (
f28e229) — Replaced the single flatChannelConfigwith 8 dedicated structs (TelegramConfig,DiscordConfig,SlackConfig,WhatsAppConfig,TrelloConfig, etc.) for cleaner config parsing, better type safety, and simpler channel-specific fields. Trelloboard_idsreplaces the previousallowed_channelsfieldsrc/config/types.rs, all channel modules,src/tui/onboarding/
0.2.43 - 2026-03-02
- Telegram full control — 16 actions + live streaming + approval buttons (
c1ba37c) —telegram_sendtool expanded fromsendto 16 actions:send,reply,edit,delete,pin,unpin,forward,send_photo,send_document,send_location,send_poll,send_buttons,get_chat,ban_user,unban_user,set_reaction. LLM response streams live into a Telegram message with▋cursor (edits every 1.5 s). Session resilience: re-fetches bot from DB if lost across restarts. Idle session timeout per-usersrc/brain/tools/telegram_send.rs,src/channels/telegram/handler.rs,src/channels/telegram/mod.rs
- Discord full control — 16 actions + session idle timeout (
3459d0b) —discord_sendtool expanded to 16 actions mirroring Telegram:send,reply,edit,delete,pin,unpin,forward,send_photo,send_document,send_location,send_poll,send_buttons,get_guild,kick_user,ban_user,set_reaction. Idle session timeout for per-user sessionssrc/brain/tools/discord_send.rs,src/channels/discord/
- Slack full control — 16 actions + sender context injection (
89c9e71) —slack_sendtool expanded to 16 actions:send,reply,react,unreact,edit,delete,pin,unpin,get_messages,get_channel,list_channels,get_user,list_members,kick_user,set_topic,send_blocks. Non-owner messages now prepend sender identity[Slack message from {uid} in channel {ch}]src/brain/tools/slack_send.rs,src/channels/slack/handler.rs
- WhatsApp typing indicator (
9f3b1fa) — Sendscomposingchat state on message receipt,pausedon completion so the user sees a native typing indicator while the agent processessrc/channels/whatsapp/handler.rs
- Tool approval — 3-button UI across all channels (
f6b8523,586cccd,816147c) — All four remote channels now show ✅ Yes / 🔁 Always (session) / ❌ No approval prompts matching the TUI, powered by channel-native interactive elements (WhatsAppButtonsMessage, Telegram inline keyboard, DiscordCreateButton, SlackSlackBlockButtonElement). "Always" sets session-levelauto_approve_sessionflag — no further prompts for that sessionsrc/channels/whatsapp/mod.rs,src/channels/telegram/mod.rs,src/channels/discord/mod.rs,src/channels/slack/mod.rs
- Tool input context in Telegram streaming indicator (
3da472a,af4b96b) — Streaming status line now shows a brief hint of what the tool is doing (e.g.⚙ bash: git status) so the user has context while waitingsrc/channels/telegram/handler.rs
- TUI auto-refresh when remote channels process messages (
7b95209) — After everyrun_tool_loopcompletion,AgentServicefires asession_updated_txnotification. The TUI listens, callingload_sessionif the updated session is the current one (and not already being processed by the TUI), or marking it as unread otherwise. Real-time TUI updates when Telegram/WhatsApp/Discord/Slack messages are processed — no manual session switch requiredsrc/brain/agent/service/builder.rs,src/brain/agent/service/tool_loop.rs,src/tui/events.rs,src/tui/app/state.rs,src/cli/ui.rs
- SQLite WAL mode + larger pool (
1ec5c3b) — Enables write-ahead logging so concurrent reads (TUI) and writes (channel agents) don't block each other; pool size increased from 5 to 20 connections. Eliminates channel concurrency timeoutssrc/services/(DB setup)
- WhatsApp sender identity (
00cc01b) — Strips device suffix from JID (:N@s.whatsapp.net→@s.whatsapp.net) before phone-number comparison; injects[WhatsApp message from {name} ({phone})]for non-owner messages; fetches contact display name when availablesrc/channels/whatsapp/handler.rs
- WhatsApp reply to chat JID instead of device JID (
24c1e5d) — Was replying to the device-scoped JID (:0@s.whatsapp.net) causing delivery failures in group chats and multi-device setups; now replies to the canonical chat JIDsrc/channels/whatsapp/handler.rs
- Inject sender context for non-owner Discord and Telegram messages (
e00374a) — Non-owner messages now prepend[Discord/Telegram message from {name} (ID {uid}) in channel {ch}]so the agent knows who it's talking to instead of assuming the ownersrc/channels/discord/handler.rs,src/channels/telegram/handler.rs
- Secret sanitization — redact API keys from all display surfaces (
436808e,d3a2380) — Newutils::redact_tool_input()function recursively walks tool input JSON, redacting values for sensitive keys (authorization,api_key,token,secret,password,bearer, etc.) and inline bash command patterns (Bearer xxx,api_key=xxx, URL passwords). Applied to TUI tool history, TUI approval dialogs, and all four remote channel approval messagessrc/utils/sanitize.rs(new),src/tui/render/tools.rs,src/channels/*/mod.rs
- WhatsApp upstream log noise suppressed (
f6b8523) — Addedwhatsapp_rust::client=errorandwhatsapp_rust=warndirectives to filter upstream TODO stub log linessrc/logging/logger.rs
- Context budget enforcement refactored (
d8ab8f0) — Extracted repeated 80%/90% compaction logic intoenforce_context_budget()helper onAgentService. 80 %: triggers LLM compaction. 90 %: hard-truncates to 80 % first, then compacts. Up to 3 retries on LLM compaction failure, then warns user to run/compactsrc/brain/agent/service/tool_loop.rs
send_message_with_tools_and_callback— Per-call approval and progress callback overrides; remote channels pass their own callbacks without touching service-level defaultssrc/brain/agent/service/messaging.rs,src/brain/agent/service/tool_loop.rs
0.2.42 - 2026-03-01
- Native Trello channel (
80c7b05) — TrelloAgent authenticates and makes credentials available for tool use. Default mode is tool-only — the AI acts on Trello only when explicitly asked viatrello_send. Opt-in polling available viapoll_interval_secsin config; when enabled, only responds to explicit@bot_usernamementions from allowed users. Board names resolved automatically — mix human-readable names and 24-char IDs freelysrc/channels/trello/(agent, client, handler, models, mod)
trello_connecttool (80c7b05) — Verify credentials, resolve boards by name, persist to config, spawn agent, confirm with open card count. Accepts comma-separated board names or IDssrc/brain/tools/trello_connect.rs
trello_sendtool — 21 actions (80c7b05) — Full Trello control without exposing credentials in URLs:add_comment,create_card,move_card,find_cards,list_boards,get_card,get_card_comments,update_card,archive_card,add_member_to_card,remove_member_from_card,add_label_to_card,remove_label_from_card,add_checklist,add_checklist_item,complete_checklist_item,list_lists,get_board_members,search,get_notifications,mark_notifications_readsrc/brain/tools/trello_send.rs
/onboard:<step>deep-links (e4975e4) — Jump directly to any onboarding step:/onboard:provider,/onboard:channels,/onboard:voice,/onboard:health, etc./doctoralias for/onboard:healthsrc/tui/app/messaging.rs,src/tui/app/state.rs,src/tui/render/help.rs
- WhatsApp voice notes silently dropped (
8e29655) — Handler was skipping all non-text messages including voice notes (ptt). Now only skips if no text AND no audio AND no imagesrc/channels/whatsapp/handler.rs
- STT key missing from channel factory (
8e29655,d0a7651) —ChannelFactorywas built withconfig.voicewhich hasstt_provider=None. All channel agents (WhatsApp, Discord, dynamic Telegram) now receive the fully resolvedVoiceConfigwithstt_provider/tts_providerpopulatedsrc/cli/ui.rs
- Channel
allowed_usersunified (e4975e4) — Removedallowed_idsfromChannelConfig, unified intoallowed_users: Vec<String>with backward-compat deserializer accepting legacy TOML integer arrays. Fixed health check false failures: Discord and Slack channel IDs were read from wrong fieldsrc/config/types.rs, channel agents
- Channel config not passed to agents (
406503b) —telegram_connect,discord_connect,slack_connectnow passrespond_toandallowed_channelsfrom persisted config to agent constructors (previously hardcoded to defaults)src/brain/tools/telegram_connect.rs,discord_connect.rs,slack_connect.rs
- Tool expand (
Ctrl+O) shows full params (0aba196) — Expanded tool view now shows complete untruncated input params line by line. In-flight calls show a "running..." spinner. DB-reconstructed entries degrade gracefullysrc/tui/render/tools.rs,src/tui/app/state.rs
- Error/warning messages auto-dismiss after 2.5 s (
4408a69,d0a7651) — Timer resets correctly on user action; covers all clear-sites in input, messaging, and dialogssrc/tui/app/dialogs.rs,input.rs,messaging.rs
- Thinking indicator sticky above input (
406503b) — Moved out of scrollable chat into a dedicated layout chunk — never scrolls awaysrc/tui/render/mod.rs,chat.rs
/onboardresets to first screen (d0a7651) — Pre-loads existing config values while resetting toModeSelectso health check shows correct statesrc/tui/app/messaging.rs,src/tui/onboarding/wizard.rs
- CI Windows build (
001ed00) — Replaced removedaws-bedrock/openaifeatures withtelegram,discord,slackin Windows CI workflow.github/workflows/ci.yml
- Trello agent tool-only by default (
7ca6b6b) — Removed automatic polling and auto-replies. Agent starts in tool-only mode (credentials stored, no polling).poll_interval_secsin[channels.trello]config opts in to polling; even then only @mentions from allowed users trigger a response. Addspoll_interval_secs: Option<u64>toChannelConfigsrc/channels/trello/agent.rs,src/config/types.rs,src/cli/ui.rs,src/brain/tools/trello_connect.rs,config.toml.example
0.2.41 - 2026-03-01
- WhatsApp onboarding — always test connection on Enter (
676ab29) — Pressing Enter on the phone field now always triggers a test message, matching Telegram/Discord/Slack behavior. Previously the test was gated onwhatsapp_connected, so re-opening the app with an existing session silently skipped the test and just advancedsrc/tui/onboarding/channels.rs
- WhatsApp onboarding — reconnect from existing session for test (
676ab29) — When no live client is in memory (app reopened after prior pairing),test_whatsapp_connectionnow callsreconnect_whatsapp()which reuses the storedsession.dbwithout wiping it — no new QR scan requiredsrc/brain/tools/whatsapp_connect.rs,src/tui/app/dialogs.rs
- WhatsApp test message includes brand header (
676ab29) — Test message now prepends🦀 *OpenCrabs*\n\n(theMSG_HEADERconstant) so it reads consistently with all other WhatsApp messages sent by the agentsrc/tui/app/dialogs.rs
- WhatsApp onboarding — post-QR UX overhaul (
676ab29) — After scanning the QR code the popup dismisses, the wizard advances to the phone allowlist field, shows any previously configured number (sentinel pattern), and allows confirm-or-replace before testing. Navigation keys (Tab/BackTab/S) always work regardless of test state; only Enter is blocked while a test is in-flightsrc/tui/onboarding/channels.rs,src/tui/onboarding_render.rs,src/tui/app/dialogs.rs,src/tui/app/state.rs,src/brain/tools/whatsapp_connect.rs
- Clippy
collapsible_matcherrors (ff66828) — Collapsed nestedif-in-matcharms into match guards acrossinput.rs(WhatsApp paste handler) andmarkdown.rs(Tag::BlockQuote,TagEnd::Heading,TagEnd::Item,Event::HardBreak|SoftBreak)src/tui/onboarding/input.rs,src/tui/markdown.rs
- CI nightly clippy/rustfmt (
a65c0ab) — Addedrustfmtandclippycomponents torust-toolchain.tomlso nightly CI jobs resolve the tools without network fallback; pinned workflow tomainbranch triggerrust-toolchain.toml,.github/workflows/
0.2.40 - 2026-02-28
- Live plan checklist widget (
7e1b4db) — A real-time task panel appears above the input box whenever the agent is executing a plan. Shows plan title, progress bar (N/M ████░░ X%), and per-task status rows (✓completed,▶in-progress,·pending,✗failed) with per-status colors. Height ismin(task_count + 2, 8)rows; zero height when no plan is active. Panel is session-isolated — each session tracks its own plan file (~/.opencrabs/agents/session/.opencrabs_plan_{uuid}.json) and reloads on session switchsrc/tui/render/plan_widget.rs(new),src/tui/render/mod.rs,src/tui/app/state.rs,src/tui/app/messaging.rs
- Live ctx counter during agent tool loops (
1cb46a9) —TokenCountUpdatedevents now synclast_input_tokensso thectx: N/Mdisplay in the status bar ticks up live during streaming and tool execution instead of freezing untilResponseCompletesrc/tui/app/state.rs
- Ctx shows base context on session load and new session (
1cb46a9) — Status bar no longer starts at–or0on a fresh session. It immediately reflects system prompt + tool definition token cost viabase_context_tokens()(system prompt tokens + tool count × 60)src/brain/agent/service/builder.rs,src/tui/app/messaging.rs
- Plan tool auto-approves on finalize (
9fca3ec) —finalizenow setsPlanStatus::Approveddirectly and instructs the agent to begin executing tasks immediately. Previously the tool returnedPendingApprovaland printed "STOP — wait for user response", causing a double-approval (tool dialog + follow-up message) and blocking task executionsrc/brain/tools/plan_tool.rs,src/brain/prompt_builder.rs
read_only_modedead code removed (9fca3ec) — Remnant field and all callers from the deleted Plan Mode feature purged fromToolExecutionContext, tool implementations,send_message_with_tools_and_mode, A2A handlers, and testssrc/tui/app/messaging.rs,src/tui/app/state.rs,src/brain/tools/bash.rs,src/brain/tools/edit_file.rs,src/brain/tools/write_file.rs,src/brain/tools/code_exec.rs,src/brain/tools/notebook.rs
- MiniMax
</think>block stripping (9b0b8d0) — MiniMax sometimes closes reasoning blocks with</think>instead of<!-- /reasoning -->. Extended the think-tag filter to handle this closing variantsrc/brain/provider/custom_openai_compatible.rs
- Complete TUI color overhaul — gray, orange, and cyan palette (
2796889,3d88f11,a33fddc) — All three legacy accent colors replaced for a cohesive warm-neutral scheme:Color::Blue/Rgb(70,130,180)→Color::Gray/Rgb(120,120,120)— borders, titles, section headersColor::Yellow/Rgb(184,134,11)→Color::Rgb(215,100,20)muted orange — active/pending states, ctx warning, approval badgeColor::Green/ green-dominantRgbvalues →Color::Cyan/Rgb(60–80,165–190,165–190)— success states, completed tasks, diff additions, ctx-ok indicatorsrc/tui/render/chat.rs,src/tui/render/dialogs.rs,src/tui/render/help.rs,src/tui/render/input.rs,src/tui/render/plan_widget.rs,src/tui/render/sessions.rs,src/tui/render/tools.rs,src/tui/onboarding_render.rs
0.2.39 - 2026-02-28
- Status bar below input (
02220e7,9dd4cab) — Persistent one-line status bar replaces the old sticky overlay. Displays session name (orange), provider / model, working directory, and approval policy badge. Session and directory were moved from the header into the status bar; the full-width header bar was removed entirelysrc/tui/render/mod.rs,src/tui/render/input.rs
- Immediate thinking spinner in chat (
57ffc40) — A spinner and "OpenCrabs is thinking..." line appears in the chat area as soon as a request is submitted, before any streaming content arrives. Eliminates the blank gap while the provider is warming upsrc/tui/render/chat.rs
- Per-session context token cache (
57ffc40) — When switching between sessions or reloading, the last known input token count is restored from an in-memory cache instead of showing–. Accurate token counts are re-confirmed on the next API responsesrc/tui/app/state.rs,src/tui/app/messaging.rs
- ctx shows accurate token count for providers that report zero usage (
033043f) — Providers like MiniMax always returnusage: {total_tokens: 0}in streaming responses. The provider now uses its pre-computedmessage_tokens + tool_schema_tokens(serialised OpenAI JSON) as the fallback, so the ctx display (e.g.29K/200K) matches the debug log exactly instead of showing the lower raw-text estimate (~14K)src/brain/provider/custom_openai_compatible.rs,src/brain/agent/service/tool_loop.rs
- Compact app title in sessions/help screens (
bc80a0f) — Removed blank lines and border from the app title block in non-chat screens. Title now occupies exactly one row, reclaiming vertical spacesrc/tui/render/mod.rs
- Extra blank space below chat history (
d469f01) — Scroll calculation usedreserved = 3left over from removed borders/overlay. Changed toreserved = 1(top padding only), eliminating the gap at the bottom of the chat areasrc/tui/render/chat.rs
- Duplicate thinking indicators removed (
aa08d68,57ffc40) — "OpenCrabs is thinking" was appearing twice: once as an inline tool-group hint and once in the status bar. Removed both; the single spinner in the chat area is the sole indicatorsrc/tui/render/chat.rs,src/tui/render/input.rs
- Muted orange replaces bright yellow (
02220e7) —Color::Yellowreplaced withColor::Rgb(215, 100, 20)for ctx percentage, sessions spinner, and pending-approval badge. Intentional dark-goldenRgb(184, 134, 11)unchangedsrc/tui/render/input.rs,src/tui/render/sessions.rs
0.2.38 - 2026-02-27
- Splash screen shows actual custom provider name —
resolve_provider_from_config()was returning the hardcoded string"Custom"instead of the actual provider name (e.g."nvidia","moonshot"). Now correctly returns the name key fromproviders.active_custom()src/config/types.rs
- Full request payload in debug logs — Removed
.take(1000)truncation from OpenAI-compatible request debug log. The API request itself was never truncated; only the log display was. Now logs the full payload for accurate debuggingsrc/brain/provider/custom_openai_compatible.rs
- Standalone reasoning render during thinking-only phase — Providers that emit reasoning before any response text (e.g. Kimi K2.5, DeepSeek) now render a visible
🦀 OpenCrabs is thinking...block with live reasoning content whilestreaming_responseis still empty. Previously the screen was blank until the first response chunksrc/tui/render/chat.rs
- Streaming redraws per chunk — Drain loop in runner now breaks immediately on
ResponseChunkevents, triggering a redraw after each text chunk. PreviouslyReasoningChunkevents also broke the loop, preventing response text from rendering in real-time on some providerssrc/tui/runner.rs
- Approval dialog shows full tool parameters — Tool approval dialog previously truncated parameter values at 60 characters. Now renders all parameters line-by-line without truncation so the full context is visible when deciding whether to approve
src/tui/render/tools.rs
- Tool approval waits indefinitely — Removed 120-second timeout on tool approval callbacks. The dialog now waits as long as needed for the user to approve or deny
src/tui/app/state.rs
- Green dot pulse slowed — Animated
●dot in tool call groups now pulses on a ~1.6s cycle (animation_frame / 8) instead of the previous fast flicker (animation_frame / 3)src/tui/render/tools.rs
- Plan Mode completely removed (~1400 lines deleted) — All plan execution code, UI, keyboard shortcuts, and state removed. Includes
plan_exec.rsmodule,AppMode::Planvariant,PlanApprovalState/PlanApprovalDatastructs, Ctrl+P/Ctrl+A/Ctrl+R/Ctrl+I shortcuts, plan approval intercept in input handler, plan help screen section, and plan re-exports. Plan Mode section removed from READMEsrc/tui/app/plan_exec.rs(deleted),src/tui/app/input.rs,src/tui/app/messaging.rs,src/tui/app/mod.rs,src/tui/app/state.rs,src/tui/events.rs,src/tui/mod.rs,src/tui/render/chat.rs,src/tui/render/help.rs,src/tui/render/mod.rs,src/tui/render/tools.rs,README.md
0.2.37 - 2026-02-26
- Per-session provider selection (
5689cd9) — Each session can now have its own LLM provider. Configure per-session via/modelsor inconfig.tomlunder[session.*.provider]. Parallel execution of multiple sessions with different providers supportedsrc/brain/agent/service.rs,src/brain/mod.rs,src/tui/app/state.rs,src/tui/render.rs,config.toml.example
- Arrow key navigation in multiline input (
9b544f9) — Arrow Up/Down now navigate between lines in the multiline input field, not just recall history. Cursor moves within the multiline content as expectedsrc/tui/app/input.rs,src/tui/render/input.rs
- Test units for multi-session and multi-model (
cf7ff0d) — Added unit tests covering session-aware approval policies, model switching within sessions, and provider key isolationsrc/brain/agent/service/tests/approval_policies.rs,src/brain/agent/service/tests/basic.rs
- Session-aware tool approvals (
846f228) — Tool approval policies now correctly apply per-session. Approval state is stored with session ID, not globally. Async model fetching improved with better error handlingsrc/brain/agent/service.rs,src/brain/mod.rs,src/tui/app/state.rs
- Custom provider name field (
c22a05a) — Onboarding now pre-fills the custom provider name field. Model fetching uses existing key if available instead of requiring re-entry. Provider name displays correctly in/modelsdialogsrc/tui/onboarding.rs,src/tui/app/dialogs.rs,src/brain/provider/custom_openai_compatible.rs
- Split
agent/service.rs(8f9c160) — Extracted into module directory:service/builder.rs,service/context.rs,service/helpers.rs,service/messaging.rs,service/mod.rs. Improved code organization and testability - Split
render.rs(6247666) — Extracted 3312-line file intorender/module directory withrender/mod.rs,render/input.rs,render/dialogs.rs,render/components.rs - Cargo fmt pass (
d02fcf7) — Full codebase formatting enforcement
0.2.36 - 2026-02-26
- Custom provider
/modelsdialog (fc0626c) — Model name is now a free-text input instead of a hardcoded list. Labels show the actual provider name (e.g. "Moonshot") instead of generic "Custom". Onboarding flow updated to matchsrc/tui/app/dialogs.rs,src/tui/render.rs,src/tui/onboarding.rs,src/config/types.rs,src/tui/app/state.rs,src/brain/provider/anthropic.rs,src/brain/provider/custom_openai_compatible.rs,README.md
- Input UX improvements (
7804ab3) — Esc scrolls viewport to bottom of conversation. Arrow Up recalls previously cleared/stashed input text. Cursor renders as a block highlighting the current character instead of a thin line. Escape timer resets when processing completes so next Esc behaves correctlysrc/tui/app/input.rs,src/tui/app/messaging.rs,src/tui/app/state.rs,src/tui/render.rs
- Strip Kimi HTML comment markup (
47b1d58) — Kimi K2.5 embeds reasoning and hallucinated tool calls as HTML comments (<!-- reasoning -->,<!-- tools-v2: -->) in the content field. Extendedfilter_think_tagsandstrip_think_blocksto strip these alongside<think>. Fixedextract_reasoningto handle multiple reasoning blocks per message. Added Moonshot/Kimi pricing (K2.5, K2 Turbo, K2) to compiled-in defaults andusage_pricing.toml.examplesrc/brain/provider/custom_openai_compatible.rs,src/pricing.rs,src/tui/app/messaging.rs,usage_pricing.toml.example
/modelsprovider switch: never overwrite user API keys (5120bf5) — Killed sentinel string"__EXISTING_KEY__"from/modelsdialog entirely. Replaced with boolean flagmodel_selector_has_existing_key. Only writes tokeys.tomlwhen user actually types a new key. Disables all other providers on disk before enabling selected one. Addedis_real_keyguard inmerge_provider_keysfor all providerssrc/config/types.rs,src/tui/app/dialogs.rs,src/tui/app/state.rs,src/tui/render.rs
- Model change context hint for agent (
ce8e422) — When user switches model via/models, a[Model changed to X (provider: Y)]hint is prepended to the next user message viapending_context(same mechanism as/cd), so the LLM is aware of the switch. TUI status message also shown in chat. Custom provider uses user-configured name (e.g. "nvidia") instead of generic label. Fallback provider key changed fromproviders.custom.defaulttoproviders.customto avoid stale config entriessrc/tui/app/dialogs.rs,src/tui/app/messaging.rs
0.2.35 - 2026-02-26
- Animated tool call dots — Green
●dot pulses (●/○) while tools are actively processing, stays solid when finished. Visually distinguishes active tool execution from completed groups - Inline thinking indicator during tool execution — "OpenCrabs is thinking..." now renders inline above the active tool group instead of as a sticky overlay, preventing overlap with tool call content
.github/CODEOWNERS— Auto-assigns@adolfousieras reviewer on all PRs
- TUI spacing improvements — Removed double blank lines between messages and tool groups. Added proper spacing before thinking sections and between thinking hint and expanded content
- Inline code background removed —
bg(Color::Black)on backtick code spans in markdown renderer removed for cleaner look. Thinking hints use subtleRgb(90,90,90)text with no background - Sudo prompt bleeding into TUI — Added
-p ""flag tosudo -Sto suppress sudo's native "Password:" prompt from writing directly to the terminal cargo fmtfull codebase pass — Enforced official Rust style guide across 92 files- Test fixes —
stream_complete()tests updated to destructure(LLMResponse, Option<String>)tuple return with reasoning assertions.write_secret_keydoctest fixed (missing import + Result return type)
0.2.34 - 2026-02-26
- Reasoning/thinking persistence — MiniMax (and other providers that emit
reasoning_content) now accumulate thinking content during streaming, persist it to DB with<!-- reasoning -->markers, and reconstruct it on session reload. Reasoning is rendered as a collapsible "Thinking" section on assistant messages - Real-time message persistence per step — Assistant text is written to DB after each tool iteration, not just at the end. Crash or disconnect mid-task no longer loses intermediate text
- Collapsible reasoning UI — Ctrl+O now toggles both tool groups and reasoning sections. Collapsed by default, expandable inline with dimmed italic style matching the streaming "Thinking..." indicator
- MiniMax intermediate text lost on reload — Tool call indices from OpenAI-compatible providers collided with the text content block at index 0 in
stream_complete(), overwriting accumulated text. Tool indices now offset by +1. Fixes #10 - TUI unresponsive after onboarding —
rebuild_agent_service()only attached the approval callback, droppingprogress_callback,message_queue_callback,sudo_callback, andworking_directory. All callbacks are now preserved from the existing agent service. Fixes #10 - Tool loop false positives eliminated — Replaced 115-line per-tool signature matching with 7-line universal input hash. Different arguments = different hash = no false detection. Same args repeated 8 times = real loop
- Chat history lost on mid-task exit — Exiting while the agent was between tool iterations discarded the conversation. Now persists accumulated text before exit
- Clippy warnings — Collapsed nested
ifstatements inservice.rsandinput.rs
0.2.33 - 2026-02-25
- Streaming
/rebuild— Live compiler output streamed to chat during build. On success, binary isexec()-replaced automatically (no prompt, no restart). Auto-clones repo for binary-only users if no source tree found - Centralized
usage_pricing.toml— Runtime-editable pricing table for all providers (Anthropic, OpenAI, MiniMax, Google, DeepSeek, Meta). Edit live, changes take effect on next/usageopen without restart. Written automatically on first run during onboarding - All-time
/usagebreakdown — Shows cost grouped by model across all sessions. Historical sessions with stored tokens but zero cost get estimated costs (yellow~$X.XXprefix). Unknown models shown as$0.00instead of silently ignored /cdcontext injection — When user changes working directory via/cd, a context hint is queued and prepended to the next message so the LLM knows about the directory change without the user having to explain. Uses newpending_contextvec on App state- Tool approval policy preservation across compaction — Compaction summary prompt now includes
## Tool Approval Policysection. All 4 continuation messages (pre-loop, mid-tool-loop, emergency, mid-loop) injectCRITICAL: Tool approval is REQUIREDwhen auto-approve is off. Agent can no longer "forget" approval policy after context resets - Dropped stream detection + retry — Detects when provider streams end without
[DONE]/MessageStop(stop_reason is None). Retries up to 2 times transparently, discarding partial responses. After 2 failures, proceeds gracefully with partial response
- Context compaction streamed, not frozen —
compact_contextusesstream_completeso the TUI event loop stays alive during compaction. Previously froze the UI for 2-5 minutes on large contexts - Compaction summary visible in chat — Summary fires via
CompactionSummaryprogress event after streaming, rendered in chat so user can see what was preserved - TUI state reset post-compaction — Resets
streaming_response+active_tool_groupon compaction so the UI is clean for continuation - Compaction request budget cap — Capped at 75% of context window with 16k token overhead (was 8k). Prevents the compaction request itself from exceeding the provider limit (was sending 359k tokens)
- Real-time context counter — Live token count updates in header during streaming
/modelspaste support — API keys can be pasted into the model selection dialog- Pricing: $0 cost for all sessions —
PricingConfigstruct usedHashMap<String, Vec<PricingEntry>>but TOML hasentries = [...]wrapper. AddedProviderBlockto match schema correctly - Pricing: MiniMax $0 — Stream chunks don't include model name. Falls back to request model
- Pricing: legacy format migration — Auto-migrates
[[usage.pricing.X]]on-disk format to current schema - Clippy: collapsible_if — Fixed in
rebuild.rsandpricing.rs
0.2.32 - 2026-02-24
- A2A Bearer token authentication -- JSON-RPC endpoint (
/a2a/v1) now supportsAuthorization: Bearer <key>whenapi_keyis configured. Agent card and health endpoints remain public for discovery. Key can be set inconfig.tomlorkeys.tomlunder[a2a] - A2A task persistence -- Tasks are persisted to SQLite (
a2a_taskstable, auto-migration) on create, complete, fail, and cancel. Active tasks are restored from DB on server startup so in-flight work survives restarts - A2A SSE streaming (
message/stream) -- Real-time task updates via Server-Sent Events per A2A spec. Each SSEdata:line is a JSON-RPC 2.0 response containing aTask,TaskStatusUpdateEvent(withfinal: trueon completion), orTaskArtifactUpdateEvent. Agent card now advertisesstreaming: true
0.2.31 - 2026-02-24
- Tool calls stacking into one giant group on reload — Removed cross-iteration merge logic that collapsed all consecutive tool groups into a single "N tool calls" block, eating intermediate text between iterations. Each iteration's
<!-- tools-v2: -->marker now produces its own collapsible group, matching live session behavior - Tool group ordering during live streaming — IntermediateText handler flushed the previous iteration's tool group after pushing the new step's text, causing tools to appear below the wrong text. Now flushes tools first, matching DB order
- Ctrl+O blocked during approval — All non-approval keys were eaten when an approval dialog was pending, preventing users from collapsing expanded tool groups to see the approval. Ctrl+O now works during approval
- Auto-collapse tool groups on approval — When an approval request arrives, all tool groups are automatically collapsed so the approval dialog is immediately visible without manual intervention
- EXA MCP fallback on empty API key — Empty string API key (
"") caused EXA to attempt direct API mode instead of free MCP. Now treats empty keys as absent, correctly falling back to MCP (aaefd3d) - Brave search registered without enabled flag —
brave_searchtool registered whenever an API key existed, ignoringenabled = falsein config.toml. Now requires bothenabled = trueand a valid API key
0.2.30 - 2026-02-24
- Agent-to-Agent (A2A) Protocol — HTTP gateway implementing A2A Protocol RC v1.0 for peer-to-peer agent communication via JSON-RPC 2.0. Supports
message/send,tasks/get,tasks/cancel. Contributed by @koatora20 in #9 - Bee Colony Debate — Multi-agent structured debate protocol based on ReConcile (ACL 2024) confidence-weighted voting. Configurable rounds with knowledge-enriched context from QMD memory search
- Dynamic Agent Card —
/.well-known/agent.jsonendpoint with skills generated from the live tool registry - A2A Documentation — Config example, README section with curl examples, TOOLS.md/SECURITY.md/BOOTSTRAP.md reference templates updated
- Tool calls vanishing from TUI — Tool call context (the collapsible bullet with tool names and output) disappeared from the chat after the agent responded. Tool group was being attached to a previous assistant message instead of rendered inline before the current response. Now matches the DB reload layout: tool calls appear above the response text, visible in both live and reloaded sessions
- Tool loop false positives —
web_searchandhttp_requestcalls with different arguments were treated as identical by the loop detector, killing legitimate multi-search flows. Signatures now include query/URL arguments. Thresholds raised (8 default, 4 for modification tools) with a 50-call history window - Tool call groups splitting on session reload — Each tool-loop iteration wrote a separate DB marker, so "2 tool calls" became two "1 tool call" entries on reload. Fixed in v0.2.31
- Brave search registered without enabled flag —
brave_searchtool was available to the agent even whenenabled = falsein config.toml. Now requires bothenabled = trueand API key - EXA MCP fallback on empty API key — Empty string API key (
"") in keys.toml caused EXA to use direct API mode instead of free MCP mode. Now treats empty keys as absent, correctly falling back to MCP - A2A: Removed unused
rusqlitedependency — A2A handler no longer pulls in rusqlite; uses existing SQLite infrastructure - A2A: UTF-8 slicing safety — Fixed potential panic on multi-byte characters in message truncation
- A2A: Restrictive CORS by default — No cross-origin requests allowed unless
allowed_originsis explicitly configured - A2A: Handler module split — Monolithic
handler.rssplit intohandler/mod.rs,handler/service.rs,handler/processing.rsfor maintainability
- A2A: Agent card uses tool registry — Skills reflect actual available tools instead of hardcoded list
- A2A: Server wiring — Proper integration with AppState, config, and tool registry
- Web search defaults in README — Updated to reflect DuckDuckGo + EXA as default (no key needed), Brave as optional
0.2.29 - 2026-02-24
- Tool Parameter Normalization — Centralized alias map in tool registry corrects common LLM parameter name mistakes (
query→pattern,cmd→command,file→path) before validation. Works across all tools - Brain Tool Reference — System prompt lists exact required parameter names for each tool
- TOOLS.md Parameter Table — New user template includes tool parameter quick-reference table
- Token Counting for OpenAI-Compatible Providers —
stream_completenow readsinput_tokensfromMessageDeltaevents. Previously always 0 for MiniMax and other OpenAI-compatible providers, causing incorrect session token totals and context percentage - Session Search UTF-8 Crash — Fixed panic on multi-byte characters when truncating message content (
floor_char_boundaryinstead of raw byte slice) - Session Search Deadlock — Search uses
try_lock()on embedding engine mutex with FTS-only fallback when backfill is running - Embedding Backfill Lock Contention — Processes one document at a time, releasing engine lock between each
- Tool Loop False Positive —
session_searchloop detector signature includesoperation:queryto distinguish calls - Grep Traversal Performance — Skips
target/,node_modules/,.git/and other heavy directories; default limit of 200 matches - Thinking Indicator Overlap — "OpenCrabs is thinking..." no longer overlaps chat content
- App Exit Hang —
process::exit()prevents tokio runtime hanging onspawn_blockingthreads - Ctrl+C Force Exit — Cancel token + 1-second timeout fallback when tools are stuck
- App Module Split —
app.rs(4,960 lines) split intostate.rs,input.rs,messaging.rs,plan_exec.rs,dialogs.rswithmod.rsdeclarations only - Doc Comments — Converted
//to///doc comments across codebase - 7 Test Fixes — Fixed
test_create_provider_no_credentials(PlaceholderProvider) and 6 onboarding tests (config pollution, channel routing)
0.2.28 - 2026-02-23
- Brain Setup Persistence — BrainSetup step loads existing
USER.md/IDENTITY.mdfrom workspace as truncated preview on re-run. No extra files — brain files are the source of truth - Brain Setup Skip —
Escto skip, unchanged inputs skip regeneration, empty inputs skip gracefully - Brain Regeneration Context — On re-run, LLM receives current workspace brain files (not static templates), preserving manual edits as context. Generated content overwrites existing files
- Splash Auto-Close — Splash screen auto-closes after 3 seconds
- Slack Debug Logging — Added debug tracing for Slack message routing (user, channel, bot_id)
- Model List Isolation — Minimax and Custom provider model lists no longer mix. Each provider loads only its own models from
config.toml.example. Previouslyload_default_models()dumped all providers into one shared list - Workspace Path Trim — Workspace path is trimmed on confirm, preventing ghost directories from trailing spaces
- HealthCheck Skipping BrainSetup — HealthCheck step returned
WizardAction::Completeimmediately, skipping BrainSetup. Now returnsWizardAction::Noneto advance to BrainSetup - Brain File Overwrite on Regeneration —
apply_config()skipped writing brain files if they already existed, even after regeneration. Now overwrites when AI-generated content is available
- Renamed
about_agent→about_opencrabs— Field and label renamed from "Your Agent" to "Your OpenCrabs" for clarity
0.2.27 - 2026-02-23
- Named Custom Providers — Define multiple named OpenAI-compatible providers via
[providers.custom.<name>](e.g.lm_studio,ollama). First enabled one is used. Legacy flat[providers.custom]format still supported
- Stream Deduplication — Fixed duplicated agent messages in chat when using LM Studio and other custom providers. Some providers send the full response in the final chunk's
messagefield — falling back tomessageafter receiving delta content duplicated everything - Database Path Tilde Expansion —
~in database path config was treated literally, creating a~/directory inside the repo. Addedexpand_tilde()to resolve to actual home directory - WhatsApp Onboarding — Fixed WhatsApp channel setup to include QR code pairing step with auto-advance, skip and retry
- Channel Onboarding Allowed Lists — Fixed missing allowed users/channels/phones input fields on Telegram, Discord, WhatsApp and Slack setup screens
- README — Provider examples updated to named custom provider format (
[providers.custom.lm_studio]) - config.toml.example — Database path uses smart default, custom providers use named format
0.2.26 - 2026-02-22
- Streaming Tool Call Accumulation — OpenRouter and Custom providers now correctly handle streaming tool calls. Added
StreamingToolCall/StreamingFunctionCallstructs with optional fields for incremental SSE deserialization, plusToolCallAccumstate machine that accumulatesid,name, andargumentsacross chunks and emits onfinish_reason: "tool_calls"or[DONE] - Input Sanitization — Paste handler strips
\r\n, takes first line only, trims whitespace. Storage layer (write_secret_key,write_key) also sanitizes before writing to TOML files - Auto-append
/chat/completions— Custom provider factory auto-appends/chat/completionsto base URLs that don't include it, preventing silent 404s - Provider + Model in Completion — Onboarding completion message now shows which provider and model were selected
- Streaming Tool Calls Failing on OpenRouter/Custom — Root cause:
StreamingToolCallstruct requiredidandtypefields but SSE continuation chunks only sendindex+function.arguments. Made all fields optional exceptindex. Removed unusedtypefield - API Key Header Panic —
headers()used.expect()which panicked on invalid key characters (e.g.\rfrom paste). Now returnsResult<HeaderMap, ProviderError>with descriptive error - Log Directory Path — Logs were stored in
cwd/.opencrabs/logs/(inside the repo) instead of~/.opencrabs/logs/(user workspace). FixedLogConfig,get_log_path(), andcleanup_old_logs()to use home directory - Config/Keys Overwrite —
Config::save()was called inapp.rsandonboarding.rs, destructively overwriting the entire TOML file. Replaced all instances with individualwrite_key()/write_secret_key()calls that read-modify-write without losing unrelated sections - Custom Provider Using Wrong Field — Custom provider used
custom_api_keywhile all other providers usedapi_key_input. Unified toapi_key_inputacross all providers - Sentinel Prepended to Key —
__EXISTING_KEY__sentinel was prepended to actual API key on paste. FixedCustomApiKeyhandlers to clear sentinel before appending new input - URL Appended to Key — Pasting from clipboard could include
\rand trailing URL text in API key field. Added paste sanitization at input handler and storage layer
- Renamed
openai.rs→custom_openai_compatible.rs— Reflects that this module handles all OpenAI-compatible APIs (OpenRouter, Minimax, Custom, LM Studio, Ollama), not just official OpenAI - Onboarding Simplified — Removed ~300 lines of dead in-memory config construction from
apply_config(); all config writes now use individualwrite_key()/write_secret_key()calls - keys.toml is Single Secret Source — All API keys, bot tokens, and search keys are stored in
~/.opencrabs/keys.toml. No more env vars or OS keyring for secrets.config.tomlholds non-sensitive settings only
0.2.25 - 2026-02-21
- Token Usage for MiniMax/OpenRouter — Added
stream_options: {include_usage: true}to streaming requests; extracts and logs token usage from final chunk - Shutdown Logo — Shows ASCII logo with rolling goodbye message on terminal when exiting
- Duplicate Messages — Fixed duplicate assistant messages appearing when IntermediateText already added content
- Tool Call Flow — Tool calls now appear as separate messages after assistant text, flowing naturally between steps
- Empty Content Rendering — Fixed assistant messages showing empty during session (was showing correctly after restart)
- Thinking Indicator — Moved "OpenCrabs is thinking..." indicator to sticky position at bottom of chat (above input field), always visible to users
- Message Ordering — Queued messages now appear at very bottom of conversation (after all assistant/tool messages), above input field
- README — Added GitHub stars call-to-action
0.2.24 - 2026-02-21
- MiniMax Provider Support — Added MiniMax as new LLM provider (OpenAI-compatible). Does not have /models endpoint, uses config_models for model list
- Onboarding Wizard — Full onboarding flow for first-time setup with provider selection
- Model Selector — Slash command
/modelsto change provider and model with live fetching, search filter - Tool Call Expanded View — Ctrl+O expands tool context with gray background; diff coloring (+ green, - red)
- API Keys in keys.toml — API keys now stored in separate
~/.opencrabs/keys.toml(chmod 600) - STT/TTS Provider Config — Added
providers.stt.groqandproviders.tts.openaiconfig sections
- MiniMax Tool Calls — Fixed tool call parsing for MiniMax (empty arguments issue)
- Context Compaction Crash — Fixed orphaned tool_result crash after compaction
- Onboarding Persistence — Provider selection and settings now persist correctly
- Model Selector Flow — Multiple fixes for persistence, search, scrolling, Enter key behavior
- Compaction Crash (400 — Orphaned tool_result) — After any trim or compaction, a
user(tool_result)message could be left at the front of history without its precedingassistant(tool_use). The Anthropic API rejects this with a 400 error, crashing the next compaction attempt. Fixed at three layers:trim_to_fitandtrim_to_targetnow calldrop_leading_orphan_tool_results()after each removal;compact_with_summaryadvanceskeep_startpast any leading orphaned tool_result messages;compact_contextskips them before sending to the API as a safety net. Conversation continues normally after compaction with no tool call drops - Compaction Summary as Assistant Message — Compaction summary was stored in a
detailsfield and hidden behind Ctrl+O. Now rendered as a real assistant chat message in the conversation flow. Tool calls that follow appear below it as normal tool groups with Ctrl+O expand/collapse - config.toml Model Priority over .env —
ANTHROPIC_MAX_MODELenv var was overwriting the model set inconfig.toml, reversing the intended priority. Nowconfig.tomlwins;.envis only a fallback when no model is configured in TOML - Stale Terminal on exec() Restart —
/rebuildhot-restart left stale rendered content from the previous process visible briefly. Terminal is now fully cleared immediately after the new process takes over
- Remove Qwen and Azure — These providers are no longer supported
- README Updated — Added MiniMax documentation, keys.toml instructions
0.2.23 - 2026-02-20
- session_search Tool — Hybrid FTS5+vector search across all chat sessions (list/search operations)
- History Paging — Cap initial display at 200k tokens, Ctrl+O loads 100k more from DB
- Onboarding Model Filter — Type to search models, Esc clears filter
- Onboard Centering — Header/footer center independently, content block centers as uniform group
- Onboard Scroll — ProviderAuth tracks focused_line for proper scroll anchoring
- Content Clipping — Content no longer clips top border on overflow screens
- Compaction Display — Now clears TUI display fully, shows summary as fresh start
- Render history_marker — Rendered as dim italic in chat view
0.2.22 - 2026-02-19
/cdCommand — Change working directory at runtime via slash command or agent NLP. Opens a directory picker (same UI as@file picker). Persists toconfig.toml. Agent can also callconfig_managerwithset_working_directoryslash_commandTool — Agent-callable tool to invoke any slash command programmatically:/cd,/compact,/rebuild,/approve, and all user-defined commands fromcommands.toml. Makes the agent aware of and able to trigger any slash command- Edit Diff Context — Edit tool now includes a compact unified diff in its output. Renderer colors
+lines green,-lines red,@@lines cyan — giving both user and agent clear visual context of changes
- Stderr Bleeding into TUI — Replaced all
unsafelibcdup2//dev/nullhacks withllama-cpp-2's propersend_logs_to_tracing(LogOptions::default().with_logs_enabled(false))API. Called once at engine init — kills all llama.cpp C-level stderr output permanently. Removedlibcdependency entirely - Compaction Summary Never Visible — System messages were rendered as a single
Spanon oneLine— Ratatui clips at terminal width, so multi-paragraph summaries were silently swallowed. Fixed: newline-aware rendering with⚡yellow label. Compaction summary now goes into expandabledetails(Ctrl+O to read) - Tool Approval Disappearing — Removed 4
messages.retain()calls that deleted approval messages immediately after denial, before the user could see or interact with them
- Install Instructions — README now includes "Make It Available System-Wide" section with symlink/copy instructions
- Brain Templates — BOOT.md, TOOLS.md, AGENTS.md updated to document
/cdandconfig_managerworking directory control
0.2.21 - 2026-02-19
- Module Restructure — Merged
src/llm/(agent, provider, tools, tokenizer) intosrc/brain/. Brain is now the single intelligence layer — no split across two top-level modules - Channel Consolidation — Moved
src/slack/,src/telegram/,src/whatsapp/,src/discord/, andsrc/voice/intosrc/channels/. All messaging integrations + voice (STT/TTS) live under one module with feature-gated submodules - Ctrl+O Expands All — Ctrl+O now toggles expand/collapse on ALL tool call groups in the session, not just the most recent one
- Tool Approval Not Rendering — Fixed approval prompts not appearing in long-context sessions when user had scrolled up.
auto_scrollis now reset totruewhen an approval arrives, ensuring the viewport scrolls to show it - Tool Call Details Move — Fixed
use of moved valuefor tool call details field in ToolCallCompleted handler
0.2.20 - 2026-02-19
/whisperCommand — One-command setup for system-wide voice-to-text. Auto-downloads WhisperCrabs binary, launches floating mic button. Speak from any app, transcription auto-copies to clipboardSystemMessageEvent — New TUI event variant for async tasks to push messages into chat
- Embedding Stderr Bleed — Suppressed llama.cpp C-level stderr during
embed_document()andembed_batch_with_progress(), not just model load. Fixes garbled TUI output during memory indexing - Slash Autocomplete Dedup — User-defined commands that shadow built-in names no longer show twice in autocomplete dropdown
- Slash Autocomplete Width — Dropdown auto-sizes to fit content instead of hardcoded 40 chars. Added inner padding on all sides
- Help Screen — Added missing
/rebuildand/whisperto/helpslash commands list - Cleartext Logging (CodeQL) — Removed all
println!calls from provider factory that wrote to stdout (corrupts TUI). Kepttracing::info!for structured logging - Stray Print Statements — Removed debug
println!from wacore encoder, replacedeprintln!in onboarding tests with silent returns
- Docker Files Relocated — Moved
docker/from project root tosrc/docker/, updated all references in README and compose.yml - Clippy Clean — Fixed collapsible_if warnings in onboarding and app,
map_or→is_some_and
0.2.19 - 2026-02-18
- Cleaner Chat UI — Replaced role labels with visual indicators:
❯for user messages,●for assistant messages. User messages get subtle dark background for visual separation. Removed horizontal dividers and input box title for a cleaner look - Alt+Arrow Word Navigation — Added
Alt+Left/Alt+Rightas alternatives toCtrl+Left/Ctrl+Rightfor word jumping (macOS compatibility) - Branding — Thinking/streaming indicators now show
🦀 OpenCrabsinstead of model name
0.2.18 - 2026-02-18
- OpenRouter Provider -- First-class OpenRouter support in onboarding wizard. One API key, 400+ models including free and stealth models (DeepSeek, Llama, Mistral, Qwen, Gemma, and more). Live model list fetched from
openrouter.ai/api/v1/models - Live Model Fetching --
/modelscommand and onboarding wizard now fetch available models live from provider APIs (Anthropic, OpenAI, OpenRouter). When a new model drops, it shows up immediately — no binary update needed. Falls back to hardcoded list if offline Provider::fetch_models()Trait Method -- All providers implement async model fetching with graceful fallback to static lists
- Onboarding Wizard -- Provider step 2 now shows live model list fetched from API after entering key. Shows "(fetching...)" while loading. OpenRouter added as 5th provider option
- Removed
cargo publishfrom CI -- Release workflow no longer attempts crates.io publish (was never configured, caused false failures)
0.2.17 - 2026-02-18
- QMD Vector Search + RRF -- qmd's
EmbeddingEngine(embeddinggemma-300M, 768-dim GGUF) wired up alongside FTS5 with Reciprocal Rank Fusion. Local model, no API key, zero cost, works offline. Auto-downloads ~300MB on first use, falls back to FTS-only when unavailable - Batch Embedding Backfill -- On startup reindex, documents missing embeddings are batch-embedded via qmd. Single-file indexes (post-compaction) embed immediately when engine is warm
- Discord Voice (STT + TTS) -- Discord bot now transcribes audio attachments via Groq Whisper and replies with synthesized voice (OpenAI TTS) when enabled
- WhatsApp Voice (STT) -- WhatsApp bot now transcribes voice notes via Groq Whisper. Text replies only (media upload for TTS pending)
- CI Release Workflow -- Fixed nightly toolchain for all build targets, added ARM64 cross-linker config
- AVX CPU Guard -- Embedding engine checks for AVX support at init; gracefully falls back to FTS-only on older CPUs
- Stderr Suppression -- llama.cpp C-level stderr output redirected to /dev/null during model load to prevent TUI corruption
0.2.16 - 2026-02-18
- QMD Crate for Memory Search -- Replaced homebrew FTS5 implementation with the
qmdcrate (BM25 search, SHA-256 content hashing, collection management). Upgradedsqlxto 0.9 (git main) to resolvelibsqlite3-syslinking conflict - Brain Files Indexed -- Memory search now indexes workspace brain files (
SOUL.md,IDENTITY.md,MEMORY.md, etc.) alongside daily compaction logs for richer search context - Dynamic Welcome Messages -- All channel connect tools (Telegram, Discord, Slack, WhatsApp) now instruct the agent to craft a creative, personality-driven welcome message on successful connection instead of hardcoded greetings
- WhatsApp Welcome Removed -- Replaced hardcoded WhatsApp welcome spawn with agent-generated message via
whatsapp_sendtool - Patches Relocated -- Moved
wacore-binarypatch frompatches/tosrc/patches/, stripped benchmarks and registry metadata
- Discord
channel_idParameter -- Optionalchannel_idinput ondiscord_connectso the bot can send welcome messages immediately after connection - Slack
channel_idParameter -- Optionalchannel_idinput onslack_connectfor the same purpose - Telegram Owner Chat ID --
telegram_connectnow sets the owner chat ID from the first allowed user at connection time - QMD Memory Benchmarks -- Criterion benchmarks for qmd store operations: index file (203µs), hash skip (18µs), FTS5 search (381µs–2.4ms), bulk reindex 50 files (11.3ms), store open (1.7ms)
0.2.15 - 2026-02-17
- Built-in FTS5 Memory Search -- Replaced external QMD CLI dependency with native SQLite FTS5 full-text search. Zero new dependencies (uses existing
sqlx), always-on memory search with no separate binary to install. BM25-ranked results with porter stemming and snippet extraction - Memory Search Always Available -- Sidebar now shows "Memory search" with a permanent green dot instead of conditional "QMD search" that required an external binary
- Targeted Index After Compaction -- After context compaction, only the updated daily memory file is indexed (via
index_file) instead of triggering a fullqmd updatesubprocess - Startup Background Reindex -- On launch, existing memory files are indexed in the background so
memory_searchis immediately useful for returning users
- FTS5 Memory Module -- New async API:
get_pool()(lazy singleton),search()(BM25 MATCH),index_file()(single file, hash-skip),reindex()(full walk + prune deleted). Schema:memory_docscontent table +memory_ftsFTS5 virtual table with sync triggers - Memory Search Tests -- Unit tests for FTS5 init, index, search, hash-based skip, and content update re-indexing
- Performance Benchmarks in README -- Real release-build numbers: ~0.4ms/query, ~0.3ms/file index, 15ms full reindex of 50 files
- Resource Footprint Table in README -- Branded stats table with binary size, RAM, storage, and FTS5 search latency
- QMD CLI Dependency -- Removed all
Command::new("qmd")subprocess calls:is_qmd_available(),ensure_collection(),search()(sync),reindex_background()
0.2.14 - 2026-02-17
- Discord Integration -- Full Discord bot with message forwarding, per-user session routing, image attachment support, proactive messaging via
discord_sendtool, and dynamic connection viadiscord_connecttool - Slack Integration -- Full Slack bot via Socket Mode (no public endpoint needed) with message forwarding, session sharing, proactive messaging via
slack_sendtool, and dynamic connection viaslack_connecttool - Secure Bot Messaging:
respond_toMode -- Newrespond_toconfig field for all platforms:"mention"(default, most secure),"all"(old behavior), or"dm_only". DMs always get a response regardless of mode - Channel Allowlists -- New
allowed_channelsconfig field restricts which group channels bots are active in. Empty = all channels. DMs always pass - Bot @Mention Detection -- Discord checks
msg.mentionsfor bot user ID, Telegram checks@bot_usernameor reply-to-bot, Slack checks<@BOT_USER_ID>in text. Bot mention text is stripped before sending to agent - Bot Identity Caching -- Discord stores bot user ID from
readyevent, Telegram fetches@usernameviaget_me()at startup, Slack fetches bot user ID viaauth.testat startup - Troubleshooting Section in README -- Documents the known session corruption issue where agent hallucinates tool calls, with workaround (start new session)
- Pending Tool Approvals Hanging Agent -- Approval callbacks were never resolved on cancel, error, supersede, or agent completion, causing the agent to hang indefinitely. All code paths now properly deny pending approvals with
response_tx.send() - Stale Approval Cleanup -- Cancel (Escape), error handler, new request, and agent completion all now send deny responses before marking approvals as denied
- Rustls Crypto Provider for Slack -- Install
ringcrypto provider at startup before any TLS connections, fixing Slack Socket Mode panics
- Proactive Message Branding Removed --
discord_send,slack_send,telegram_sendtools no longer prependMSG_HEADERto outgoing messages - Agent Logging -- Improved iteration logging: shows "completed after N tool iterations" or "responded with text only"
- Auto-Approve Feedback -- Selecting "Allow Always" now shows a system message confirming auto-approve is enabled for the session
0.2.13 - 2026-02-17
- Proactive WhatsApp Messaging -- New
whatsapp_sendagent tool lets the agent send messages to the user (or any allowed phone) at any time, not just in reply to incoming messages - WhatsApp Welcome Message -- On successful QR pairing, the agent sends a fun random crab greeting to the owner's WhatsApp automatically
- WhatsApp Message Branding -- All outgoing WhatsApp messages are prefixed with
🦀 *OpenCrabs*header so users can distinguish agent replies from their own messages - WhatsApp
device_sent_messageUnwrapping -- Recursiveunwrap_message()handles WhatsApp's nested message wrappers (device_sent_message,ephemeral_message,view_once_message,document_with_caption_message) to extract actual text content from linked-device messages - Fun Startup/Shutdown Messages -- Random crab-themed greetings on launch and farewell messages on exit (10 variants each)
- WhatsApp Self-Chat Messages Ignored -- Messages from the user's own phone were dropped because
is_from_me: true; now only skips messages with the agent'sMSG_HEADERprefix to prevent echo loops while accepting user messages from linked devices - WhatsApp Phone Format Mismatch -- Allowlist comparison failed because config stored
+351...but JID user part was351...;sender_phone()now strips@s.whatsapp.netsuffix, allowlist check strips+prefix - Model Name Missing from Thinking Spinner -- "is thinking" showed without model name because
session.modelcould beSome(""); added.filter(|m| !m.is_empty())fallback todefault_model_name - WhatsApp SQLx Store Device Serialization -- Device state now serialized via
rmp-serde(MessagePack) instead of brokenbincode; addedrmp-serdedependency under whatsapp feature
wacore-binaryDirect Dependency -- Added as direct optional dependency forJidtype access (needed bywhatsapp_sendandwhatsapp_connecttools for JID parsing)
/modelSlash Command -- Removed redundant/modelcommand;/modelsalready provides model switching with selected-model display
0.2.12 - 2026-02-17
- WhatsApp Integration -- Chat with your agent via WhatsApp Web. Connect dynamically at runtime ("connect my WhatsApp") or from the onboarding wizard. QR code pairing displayed in terminal using Unicode block characters, session persists across restarts via SQLite
- WhatsApp Image Support -- Send images to the agent via WhatsApp; they're downloaded, base64-encoded, and forwarded to the AI backend for multimodal analysis
- WhatsApp Connect Tool -- New
whatsapp_connectagent tool: generates QR code, waits for scan (2 min timeout), spawns persistent listener, updates config automatically - Onboarding: Messaging Setup -- New step in both QuickStart and Advanced onboarding modes to enable Telegram and/or WhatsApp channels right after provider auth
- Channel Factory -- Shared
ChannelFactoryfor creating channel agent services at runtime, used by both static startup and dynamic connection tools - Custom SQLx WhatsApp Store --
wacore::store::Backendimplementation using the project's existingsqlxSQLite driver, avoiding thelibsqlite3-sysversion conflict withwhatsapp-rust-sqlite-storage(Diesel-based). 15 tables, 33 trait methods, full test coverage - Nightly Rust Requirement --
wacore-binaryrequires#![feature(portable_simd)]; addedrust-toolchain.tomlpinning to nightly. Local patch forwacore-binaryfixesstd::simd::SelectAPI breakage on latest nightly
- Version Numbering -- Corrected from 0.2.2 to 0.2.11 (following 0.2.1), this release is 0.2.12
0.2.11 - 2026-02-16
- Context Token Display -- TUI context indicator showed inflated values (e.g.
640K/200K) becauseinput_tokenswas accumulated across all tool-loop iterations instead of using the last API call's actual context size; nowAgentResponse.context_tokenstracks the last iteration'sinput_tokensfor accurate display whileusagestill accumulates for correct billing - Per-Message Token Count --
DisplayMessage.token_countnow shows only output tokens (the actual generated content) instead of the inflatedinput + outputsum which double-counted shared context - Clippy Warning -- Fixed
redundant_closurewarning intrim_messages_to_budget
- Compaction Threshold -- Lowered auto-compaction trigger from 80% to 70% of context window for earlier, safer compaction with more headroom
- Token Counting --
trim_messages_to_budgetnow uses tiktoken (cl100k_base) instead ofchars/3heuristic; history budget targets 60% of context window (was 70%) to leave more room for tool results
- 2 New Tests --
test_context_tokens_is_last_iteration_not_accumulatedandtest_context_tokens_equals_input_tokens_without_toolsverifying correct context vs billing token separation (450 total)
- Dead Code -- Removed unused
format_token_countfunction and its 5 tests fromrender.rs
0.2.1 - 2026-02-16
- Config Management Tool -- New
config_manageragent tool with 6 operations:read_config,write_config,read_commands,add_command,remove_command,reload; the agent can now read/writeconfig.tomlandcommands.tomlat runtime - Commands TOML Migration -- User-defined slash commands now stored in
commands.toml([[commands]]array) instead ofcommands.json; existingcommands.jsonfiles auto-migrate on first load - Settings TUI Screen -- Press
Sfor a real Settings screen showing: current provider/model, approval policy, user commands summary, QMD memory search status, and file paths (config, brain, working directory) - Approval Policy Persistence --
/approvecommand now saves the selected policy to[agent].approval_policyinconfig.toml; policy is restored on startup instead of always defaulting to "ask" - AgentConfig Section -- New
[agent]config section withapproval_policy("ask" / "auto-session" / "auto-always") andmax_concurrent(default: 4) fields - Live Config Reload --
Config::reload()method andTuiEvent::ConfigReloadedevent for refreshing cached config values after tool writes - Config Write Helper --
Config::write_key(section, key, value)safely merges key-value pairs intoconfig.tomlwithout overwriting unrelated sections - Command Management Helpers --
CommandLoader::add_command()andCommandLoader::remove_command()for atomic command CRUD - 20 New Tests -- 14 onboarding tests (key handlers, mode select, provider navigation, API key input, field flow, validation, model selection, workspace/health/brain defaults) + 6 config tests (AgentConfig defaults, TOML parsing, write_key merge, save round-trip) -- 443 total
- config.toml.example -- Added
[agent]and[voice]example sections with documentation - Commands Auto-Reload -- After
ConfigReloadedevent, user commands are refreshed fromcommands.toml
0.2.0 - 2026-02-15
- 3-Tier Memory System -- OpenCrabs now has a layered memory architecture: (1) Brain MEMORY.md -- user-curated durable memory loaded into system brain every turn, (2) Daily Memory Logs -- auto-compaction summaries saved to
~/.opencrabs/memory/YYYY-MM-DD.mdwith multiple compactions per day stacking in the same file, (3) Memory Search --memory_searchtool backed by QMD for semantic search across all past daily logs - Memory Search Tool -- New
memory_searchagent tool searches past conversation logs via QMD (qmd query --json); gracefully degrades if QMD is not installed, returning a hint to useread_fileon daily logs directly - Compaction Summary Display -- Auto-compaction at 80% context now shows the full summary in chat as a system message instead of running silently; users see exactly what the agent remembered
- Scroll While Streaming -- Users can scroll up during streaming without being yanked back to the bottom;
auto_scrollflag disables on user scroll, re-enables when scrolled back to bottom or on message send - QMD Auto-Index -- After each compaction,
qmd updateis triggered in the background to keep the memory search index current - Memory Module -- New
src/memory/mod.rsmodule with QMD wrapper: availability check, collection management, search, and background re-indexing - Path Consolidation -- All data now lives under
~/.opencrabs/(config, database, brain, memory, history, logs) - Context Budget Awareness -- Tool definition overhead (~500 tokens per tool) now factored into context usage calculation, preventing "prompt too long" errors
- Compaction Target -- Compaction summaries now write to daily logs (
~/.opencrabs/memory/YYYY-MM-DD.md) instead of appending to brain workspaceMEMORY.md; brainMEMORY.mdremains user-curated and untouched by auto-compaction - Local Timestamps -- Daily memory logs use
chrono::Localinstead of UTC for human-readable timestamps
0.1.9 - 2026-02-15
- Cursor Navigation -- Full cursor movement in input: Left/Right arrows, Ctrl+Left/Right word jump, Home/End, Delete key, Backspace at cursor position, word delete (Alt/Ctrl+Backspace), character and paste insertion at cursor position, cursor renders at correct position
- Input History Persistence -- Command history saved to
~/.config/opencrabs/history.txt(one line per entry), loaded on startup, appended on each send, capped at 500 entries, survives restarts - Real-time Streaming -- Added
stream_complete()method that streams text chunks from the provider viaStreamingChunkprogress events, replacing the old blockingprovider.complete()call - Streaming Spinner -- Animated spinner shows
"claude-opus is responding..."with streamed text below;"thinking..."spinner shows only before streaming begins - Inline Plan Approval -- Plan approval now renders as an interactive inline selector with arrow keys (Approve / Reject / Request Changes / View Plan) instead of plain text Ctrl key instructions
- Telegram Photo Support -- Incoming photos download at largest resolution, saved to temp file, forwarded as
<<IMG:path>>caption; image documents detected viaimage/*MIME type; temp files cleaned up after 30 seconds - Error Message Rendering --
app.error_messageis now rendered in the chat UI (was previously set but never displayed) - Default Model Name -- New sessions show the actual provider model name (e.g.
claude-opus-4-6) as placeholder instead of generic "AI" - Debug Logging --
DEBUG_LOGS_LOCATIONenv var sets custom log directory;--debugCLI flag enables debug mode - 8 New Tests --
stream_complete_text_only,stream_complete_with_tool_use,streaming_chunks_emitted,markdown_to_telegram_html_*,escape_html,img_marker_format(412 total)
- SSE Parser Cross-Chunk Buffering -- TCP chunks splitting JSON events mid-string caused
EOF while parsing a stringerrors and silent response drops; parser now buffers partial lines across chunks withArc<Mutex<String>>, only parsing complete newline-terminated lines - Stale Approval Cleanup -- Old
Pendingapproval messages permanently hid streaming responses; now cleared on new message send, new approval request, and response completion - Approval Dialog Reset --
approval_auto_alwaysreset on session create/load; inline "Always" now setsapproval_auto_session(resets on session change) instead ofapproval_auto_always - Brain File Path -- Brain prompt builder used wrong path for workspace files
- Abort During Streaming -- Cancel token properly wired through streaming flow for Escape×2 abort
- README -- Expanded self-sustaining section with
/rebuildcommand,SelfUpdatermodule, session persistence, brain live-editing documentation
0.1.8 - 2026-02-15
- Image Input Support -- Paste image paths or URLs into the input; auto-detected and attached as vision content blocks for multimodal models (handles paths with spaces)
- Attachment Indicator -- Attached images show as
[IMG1:filename.png]in the input box title bar; user messages display[IMG: filename.png] - Tool Context Persistence -- Tool call groups are now saved to the database and reconstructed on session reload; no more vanishing tool history
- Intermediate Text Display -- Agent text between tool call batches now appears interleaved in the chat, matching Claude Code's behavior
- Tool Descriptions Showing "?" -- Approval dialog showed "Edit ?" instead of file paths; fixed parameter key mismatches (
pathnotfile_path,operationnotaction) - Raw Tool JSON in Chat --
[Tool: read_file]{json}was dumped into assistant messages; now only text blocks are displayed, tool calls shown via the tool group UI - Loop Detection Wrong Keys -- Tool loop detection used
file_pathfor read/write/edit; fixed topath - Telegram Text+Voice Order -- Text reply now always sent first, voice note follows (was skipping text on TTS success)
- base64 dependency -- Re-added
base64 = "0.22.1"for image encoding (was removed in dep cleanup but now needed)
0.1.7 - 2026-02-14
- Voice Integration (STT) -- Incoming Telegram voice notes are transcribed via Groq Whisper (
whisper-large-v3-turbo) and processed as text by the agent - Voice Integration (TTS) -- Agent replies to voice notes with audio via OpenAI TTS (
gpt-4o-mini-tts,ashvoice); falls back to text if TTS is disabled or fails - Onboarding: Telegram Setup -- New wizard step with BotFather instructions, bot token input (masked), and user ID guidance; auto-detects existing env/keyring values
- Onboarding: Voice Setup -- New wizard step for Groq API key (STT) and TTS toggle with
ashvoice label; auto-detectsGROQ_API_KEYfrom environment - Sessions Dialog: Context Info --
/sessionsnow shows token count per session (12.5K tok,2.1M tok) and live context window percentage for the current session with color coding (green/yellow/red) - Tool Descriptions in Approval -- Approval dialog now shows actual file paths and parameters (e.g. "Edit /src/tui/render.rs") instead of raw tool names ("edit_file")
- Shared Telegram Session -- Owner's Telegram messages now use the same session as the TUI terminal; no more separate sessions that could pick the wrong model
- Provider Priority -- Factory order changed to Qwen → Anthropic → OpenAI; Anthropic is now always preferred over OpenAI for text generation
- OPENAI_API_KEY Isolation --
OPENAI_API_KEYno longer auto-creates an OpenAI text provider; it is only used for TTS (gpt-4o-mini-tts), never for text generation unless explicitly configured - Async Terminal Events -- Replaced blocking
crossterm::event::poll()with asyncEventStream+tokio::select!to prevent TUI freezes during I/O-heavy operations
- Model Contamination --
OPENAI_API_KEYin.envwas causing GPT-4 to be used for text instead of Anthropic Claude; multi-layered fix across factory, env overrides, and TTS key sourcing - Navigation Slowdown -- TUI became sluggish after losing terminal focus due to synchronous 100ms blocking poll in async context
- Context Showing 0% -- Loading an existing session showed 0% context; now estimates tokens from message content until real API usage arrives
- Approval Spam -- "edit_file -- approved" messages no longer clutter the chat; approved tool calls are silently removed since the tool group already shows execution progress
- 6 Clippy Warnings -- Fixed collapsible_if (5) and manual_find (1) across onboarding and telegram modules
0.1.6 - 2026-02-14
- Telegram Bot Integration -- Chat with OpenCrabs via Telegram alongside the TUI; bot runs as a background task with full tool access (file ops, search, bash, etc.)
- Telegram Allowlist -- Only allowlisted Telegram user IDs can interact;
/startcommand shows your ID for easy setup - Telegram Markdown→HTML -- Agent responses are formatted as Telegram-safe HTML with code blocks, inline code, bold, and italic support
- Telegram Message Splitting -- Long responses automatically split at 4096-char Telegram limit, breaking at newlines
- Grouped Tool Calls -- Multiple tool calls in a single agent turn now display as a collapsible group with tree lines (├─ └─) instead of individual messages
- Claude Code-Style Approval -- Tool approval dialog rewritten as vertical selector with
❯ Yes / Always / Nomatching Claude Code's UX - Emergency Compaction Retry -- If the LLM provider returns "prompt too long", automatically compact context and retry instead of failing
- Token Estimation -- Changed from
chars/4tochars/3for more conservative estimation, preventing context overflows that the old estimate missed - Compaction Accounts for Tools -- Auto-compaction threshold now reserves ~500 tokens per registered tool for schema overhead, preventing "prompt too long" errors
- Telegram Feature Default --
telegramfeature now included in default features (no need for--features telegram)
- Context % Showing 2369% --
context_usage_percent()was summing all historical token counts; now uses only the latest response'sinput_tokens - TUI Lag After First Request --
active_tool_groupwasn't cleaned up on error/abort paths, causing UI to hang - Telegram Bot No Response -- Bot was calling
send_message(no tools) instead ofsend_message_with_tools; also neededauto_approve_tools: truesince there's no TUI for approval
0.1.5 - 2026-02-14
- Context Usage Indicator -- Input box shows live
Context: X%with color coding: green (<60%), yellow (60-80%), red (>80%) so you always know how close you are to the context limit - Auto-Compaction -- When context usage exceeds 80%, automatically sends conversation to the LLM for a structured breakdown summary (Current Task, Key Decisions, Files Modified, Current State, Important Context, Errors & Solutions), saves to MEMORY.md, and trims context keeping the last 8 messages + summary for seamless continuation
/compactCommand -- Manually trigger context compaction at any time via slash command- Brave Search Tool -- Real-time web search via Brave Search API (set
BRAVE_API_KEY); great if you already have a Brave API key or want a free-tier option - EXA Search Tool -- Neural-powered web search via EXA AI; works out of the box via free hosted MCP endpoint (no API key needed). Set
EXA_API_KEYfor direct API access with higher rate limits
- EXA Always Available -- EXA search registers unconditionally via free MCP endpoint; Brave still requires
BRAVE_API_KEY
0.1.4 - 2026-02-14
- Inline Tool Progress -- Tool executions now show inline in chat with human-readable descriptions (e.g. "Read src/main.rs", "bash: cargo check", "Edited src/app.rs") instead of invisible spinner
- Expand/Collapse Tool Details -- Press Ctrl+O to expand or collapse tool output details on completion messages, inspired by Claude Code's UX
- Abort Processing -- Press Escape twice within 3 seconds to cancel an in-progress agent request via CancellationToken
- Active Input During Processing -- Input box stays active with cursor visible while agent is processing; border remains steel blue
- Processing Guard -- Prevents sending a second message while one is already processing; shows "Please wait or press Esc x2 to abort"
- Progress Callback System -- New
ProgressCallback/ProgressEventarchitecture emittingThinking,ToolStarted, andToolCompletedevents from agent service to TUI - LLM-Controlled Bash Timeout -- Bash tool now accepts
timeout_secsfrom the LLM (capped at 600s), default raised from 30s to 120s
- Silent Auto-Approved Tools -- Auto-approved tool calls no longer spam the chat; only completion descriptions shown
- Approval Never Times Out -- Tool approval requests wait indefinitely until the user acts (no more 5-minute timeout)
- Approval UI De-Emojified -- All emojis removed from approval rendering; clean text-only UI
- Yolo Mode Always Visible -- All three approval tiers (Allow once, Allow all session, Yolo mode) always visible with color-coding (green/yellow/red) in inline approval
- Race Condition on Double Send -- Added
is_processingguard insend_message()preventing overlapping agent requests
0.1.3 - 2026-02-14
- Inline Tool Approval — Tool permission requests now render inline in chat instead of a blocking overlay dialog, with three options: Allow once, Allow all for this task, Allow all moving forward
/approveCommand — Resets tool approval policy back to "always ask"- Word Deletion — Ctrl+Backspace and Alt+Backspace delete the last word in input
- Scroll Support — Arrow keys and Page Up/Down now scroll Help, Sessions, and Settings screens
- Tool Approval Docs — README section documenting inline approval keybindings and options
- Ctrl+C Behavior — First press clears input, second press within 3 seconds quits (was immediate quit)
- Help Screen — Redesigned as 2-column layout filling full terminal width instead of narrow single column
- Status Bar Removed — Bottom status bar eliminated for cleaner UI; mode info shown in header only
- Ctrl+H Removed — Help shortcut removed (use
/helpinstead); fixes Ctrl+Backspace conflict where terminals send Ctrl+H for Ctrl+Backspace
- MCP Module — Deleted empty placeholder
src/mcp/directory (unused stubs, zero functionality) - Overlay Approval Dialog — Replaced by inline approval in chat
- Bottom Status Bar — Removed entirely for more screen space
0.1.2 - 2026-02-14
- Onboarding Wizard — 8-step wizard with QuickStart/Advanced modes for first-time setup
- AI Brain Personalization — Generates all 6 workspace brain files (SOUL, IDENTITY, USER, AGENTS, TOOLS, MEMORY) from user input during onboarding
- Session Management —
/sessionscommand, rename sessions (R), delete sessions (D) from session list - Mouse Scroll — Mouse wheel scrolls chat history
- Dynamic Input Height — Input area grows with content, 1-line default
- Screenshots — Added UI screenshots to README (splash, onboarding, chat)
- Unified Anthropic Provider — Auto-detects OAuth tokens vs API keys from env/keyring
- Pre-wrapped Chat Lines — Consistent left padding for all chat messages
- Updated Model List — Added
claude-opus-4-6,gpt-5.1-codex-mini,gemini-3-flash-preview,qwen3-coder-next - Cleaner UI — Removed emojis, reordered status bar
- README — Added screenshots, updated structure
0.1.1 - 2026-02-14
- Dynamic Brain System — Replace hardcoded system prompt with brain loader that reads workspace MD files (SOUL, IDENTITY, USER, AGENTS, TOOLS, MEMORY) per-turn from
~/opencrab/brain/workspace/ - CommandLoader — User-defined slash commands via
commands.json, auto-reloaded after each agent response - SelfUpdater — Build/test/restart via Unix
exec()for hot self-update (/rebuildcommand) - RestartPending Mode — Confirmation dialog in TUI after successful rebuild
- Onboarding Docs — Scaffolding for onboarding documentation
- system_prompt → system_brain — Renamed across entire codebase to reflect dynamic brain architecture
/helpFixed — Opens Help dialog instead of pushing text message into chat
0.1.0 - 2026-02-14
- Anthropic OAuth Support — Claude Max / setup-token authentication via
ANTHROPIC_MAX_SETUP_TOKENwith automaticsk-ant-oatprefix detection,Authorization: Bearerheader, andanthropic-beta: oauth-2025-04-20header - Claude 4.x Models — Support for
claude-opus-4-6,claude-sonnet-4-5-20250929,claude-haiku-4-5-20251001with updated pricing and context windows .envAuto-Loading —dotenvyintegration loads.envat startup automatically- CHANGELOG.md — Project changelog following Keep a Changelog format
- New Branding — OpenCrab ASCII art, "Shell Yeah! AI Orchestration at Rust Speed." tagline, crab icon throughout
- Rust Edition 2024 — Upgraded from edition 2021 to 2024
- All Dependencies Updated — Every crate bumped to latest stable (ratatui 0.30, crossterm 0.29, pulldown-cmark 0.13, rand 0.9, dashmap 6.1, notify 8.2, git2 0.20, zip 6.0, tree-sitter 0.25, thiserror 2.0, and more)
- Rebranded — "OpenCrab AI Assistant" renamed to "OpenCrab AI Orchestration Agent" across all source files, splash screen, TUI header, system prompt, and documentation
- Enter to Send — Changed message submission from Ctrl+Enter (broken in many terminals) to plain Enter; Alt+Enter / Shift+Enter inserts newline for multi-line input
- Escape Double-Press — Escape now requires double-press within 3 seconds to clear input, preventing accidental loss of typed messages
- TUI Header Model Display — Header now shows the provider's default model immediately instead of "unknown" until first response
- Splash Screen — Updated with OpenCrab ASCII art, new tagline, and author attribution
- Default Max Tokens — Increased from 4096 to 16384 for modern Claude models
- Default Model — Changed from
claude-3-5-sonnet-20240620toclaude-sonnet-4-5-20250929 - README.md — Complete rewrite: badges, table of contents, OAuth documentation, updated providers/models, concise structure (764 lines vs 3,497)
- Project Structure — Moved
tests/,migrations/,benches/,docs/insidesrc/and updated all references
- pulldown-cmark 0.13 API —
Tag::Headingtuple to struct variant,Event::EndwrapsTagEnd,Tag::BlockQuotetakes argument - ratatui 0.29+ —
f.size()replaced withf.area(),Backend::Errorbounds added (Send + Sync + 'static) - rand 0.9 —
thread_rng()replaced withrng(),gen_range()replaced withrandom_range() - Edition 2024 Safety — Removed unsafe
std::env::set_var/remove_varfrom tests, replaced with TOML config parsing
- Outdated "Claude Max OAuth is NOT supported" disclaimer (it now is)
- Sprint history and "coming soon" filler from README
- Old "Crusty" branding and attribution