shinychat 0.4.0
CRAN release: 2026-06-01
Experimental internal changes
- The chat UI’s rendering layer has been migrated from Lit to React. This significantly improves streaming performance — incoming chunks no longer clear previous DOM state — and makes the codebase more maintainable. One trade-off is that certain Shiny UI elements embedded in chat messages may not work as well as before (e.g., inline
<script>tags are generally not supported inside a React runtime). If you encounter issues, please let us know.
New features and improvements
The chat UI now displays model reasoning/thinking content as collapsible panels above assistant responses. Thinking content streams in real-time with animated topic labels. This works with providers that support structured thinking (e.g., Claude’s extended thinking via
ellmer) and with local models that wrap reasoning in<thinking>tags. (#208)Added
enable_cancelparameter tochat_ui()to show a stop button that lets users cancel an in-progress AI response. Press the stop button or hit Escape to cancel.chat_mod_ui()enables cancellation by default, andchat_mod_server()handles the cancellation wiring automatically, using the stream cancellation features introduced in ellmer v0.4.1. (#221)Markdown lists where every item is a
<span class="suggestion">are now rendered as a grid of clickable suggestion cards. Each suggestion’s text content becomes both the card label and the value sent on click. To add a short heading above the body text, set thetitleattribute on the span — e.g.<span class="suggestion" title="Heading">Body text shown on the card.</span>. Only the body text (not the title) is submitted when the card is clicked. Cards stream in with staggered animations and support keyboard navigation (arrow keys, Home/End) with roving tabindex. (#219)Added
chat_greeting()for creating welcome messages that appear when the chat is empty. Greetings can be set statically viachat_ui(greeting=)or dynamically from the server withchat_set_greeting(). They are automatically dismissed when the user sends their first message. A newgreeting_requestedinput fires when the chat is visible, empty, and has no greeting, enabling LLM-generated welcome messages.chat_mod_server(greeting=)accepts a function for auto-generated greetings. (#217)Tool result cards now render images and PDFs returned by ellmer tools. When a tool returns
content_image_file(),content_image_url(), orcontent_pdf_file(), the result is displayed as an inline image or a PDF filename badge. Mixed content lists (e.g.,list(ContentText("summary"), content_image_file("plot.png"))) are rendered with items interleaved in order. (#225)Added
footerparameter tochat_ui()for displaying arbitrary HTML content below the chat input. Useful for disclaimers, attribution, or interactive toolbars. Styled with sensible defaults and customizable via--shiny-chat-footer-font-sizeand--shiny-chat-footer-colorCSS custom properties. (#224)Tool result cards now support a fullscreen toggle. Set
full_screen = TRUEin thedisplaylist (or setres$full_screen <- NAin a customcontents_shinychat()method) to add a button that expands the card to fill the viewport. PressEscape, click the backdrop, or use the close button to exit fullscreen.Added
footerfield toToolResultDisplayfor displaying custom HTML content below the tool result card body. (#178)chat_mod_server()now returns aset_client(new_client, sync = TRUE)function for swapping the chat client used by the module at runtime. Whensync = TRUE(the default), the new client inherits the current conversation’s turns, system prompt, and tools so the conversation continues seamlessly. If a response is currently streaming, the swap is deferred until the stream completes. (#227)chat_mod_server()now returns astatusreactive that reports the current interaction state:"idle"when no response is in progress, or"streaming"while a response is actively being received. (#227)chat_restore()now invisibly returns a cancel function that tears down all bookmark registrations made by that call. This is useful when swapping the chat client viaset_client(), which handles the re-registration automatically. (#227)
Improvements
- All navigating links in assistant messages now open in a new tab to preserve the app’s session state. Cross-origin links still show the confirmation dialog; same-origin links open directly. (#238)
Bug fixes
Fixed the external link confirmation dialog not rendering in Safari. The backdrop overlay appeared but the dialog content was invisible due to a Bootstrap/
<dialog>CSS interaction. (#201, #238)Fixed pressing Escape to dismiss the external link dialog leaving it in a broken state where subsequent link clicks no longer worked. (#238)
Fixed an issue where user chat messages would display the default assistant icon. (#162)
shinychat 0.3.0
CRAN release: 2025-11-20
Breaking changes
-
chat_mod_server()now returns a list of reactives forlast_inputandlast_turn, as well functions toupdate_user_input(),append()andclear()the chat. (#130, #143, #145)
New features
Added
chat_restore()which adds Shiny bookmarking hooks to save and restore the ellmer chat client. (#28, #82)Added
update_chat_user_input()for programmatically updating the user input of a chat UI element. (#78)shinychat now shows tool call request and results in the UI, and the feature is enabled by default in
chat_app()and the chat module (chat_mod_server()). When usingchat_append()withchat_ui(), setstream = "content"when you call the$stream_async()method on theellmer::Chatclient to ensure tool calls are included in the chat stream output. Learn more in the tool calling UI article. (#52)Added
chat_append(icon=...)andchat_ui(icon_assistant=...)for customizing the icon that appears next to assistant responses. (#88)
Improvements
chat_app()now correctly restores the chat client state when refreshing the app, e.g. by reloading the page. (#71)External links in chat messages in
chat_ui()now open in a new tab by default, with a confirmation dialog. (#120)
Bug fixes
- The chat input no longer submits incomplete text when the user has activated IME completions (e.g. while typing in Japanese or Chinese). (#85)
Internal changes
We consolidated the
<shiny-chat-message>and<shiny-user-message>components into a single<shiny-chat-message>component with adata-roleattribute to indicate whether it’s an “assistant” or “user” message. This likely has minimal impact on your apps, other than custom styles. You should update anyshiny-user-messagerules to useshiny-chat-message[data-role="user"]. (#101)The chat UI’s send input button is now identified by the class
.shiny-chat-btn-send. (@DeepanshKhurana, #138)
shinychat 0.2.0
CRAN release: 2025-05-16
New features and improvements
Added new
output_markdown_stream()andmarkdown_stream()functions to allow for streaming markdown content to the client. This is useful for showing Generative AI responses in real-time in a Shiny app, outside of a chat interface. (#23)Both
chat_ui()andoutput_markdown_stream()now support arbitrary Shiny UI elements inside of messages. This allows for gathering input from the user (e.g.,selectInput()), displaying of rich output (e.g., htmlwidgets like plotly), and more. (#29)Added a new
chat_clear()function to clear the chat of all messages. (#25)Added
chat_app(),chat_mod_ui()andchat_mod_server().chat_app()takes an ellmer chat client and launches a simple Shiny app interface with the chat.chat_mod_ui()andchat_mod_server()replicate the interface as a Shiny module, for easily adding a simple chat interface connected to a specific ellmer chat client. (#36)The promise returned by
chat_append()now resolves to the content streamed into the chat. (#49)
Bug fixes
chat_append(),chat_append_message()andchat_clear()now all work in Shiny modules without needing to namespace theidof the Chat component. (#37)chat_append()now logs and throws a silent error if the stream errors for any reason. This prevents the app from crashing if the stream is interrupted. You can still usepromises::catch()to handle the error in your app code if desired. (#46)