Explainability and feedback, embedded exactly where AI output is served.
When AI outputs need to be questioned, explained, or challenged, that should happen right there on the screen. Not in a form. Not in a meeting. MUS makes that possible for any AI product that has a web face.
Wrap any output with <FeedbackTarget>. Users hover. A toolbar appears exactly where the output lives.
Try the live, click-through version at mus.datachef.co.
import { MusProvider, FeedbackTarget } from '@datachef/mus'
import '@datachef/mus/styles.css'
function App() {
return (
<MusProvider config={{
projectName: 'My App',
slack: {
proxyUrl: '/api/slack-proxy',
supportTeamEmails: ['you@yourteam.com'],
feedbackChannelId: 'C0XXXXXXXXX',
},
}}>
<FeedbackTarget sectionId="ai-summary" sectionName="AI Summary">
<AISummaryOutput />
</FeedbackTarget>
</MusProvider>
)
}One hover. No forms. No context switching. The reaction lands in your Slack, attached to the exact section.
| Action | What happens |
|---|---|
| 💬 Support | Opens a dedicated Slack channel between the user and your team. One click, full context already attached |
| 🎤 Voice | Records a voice clip (up to 3 min), converted to MP3 and posted to Slack with the section name |
| 👍 / 👎 Thumbs | Fire-and-forget: instant signal, zero friction |
| ▶ Video | Plays an explainer video attached to that section. Context that stays, not a one-time tour |
npm install @datachef/musFor voice feedback, also install the optional audio converter:
npm install ffmpeg-static # optional; falls back to system ffmpegThe package ships ready-made server handlers. Keep SLACK_BOT_TOKEN on the server and never in the browser.
// app/api/mus/voice-upload/route.ts
export { POST } from '@datachef/mus/server'
// app/api/mus/standalone-upload/route.ts
export { POSTStandalone as POST } from '@datachef/mus/server'
// app/api/mus/support-channel/route.ts
export { POSTSupportChannel as POST } from '@datachef/mus/server'# .env.local
SLACK_BOT_TOKEN=xoxb-your-bot-tokenimport { createMusHandlers } from '@datachef/mus/server'
import { slackAdapter } from '@datachef/mus/adapters/slack'
import { discordAdapter } from '@datachef/mus/adapters/discord'
export const { POST, POSTStandalone, POSTSupportChannel } = createMusHandlers({
adapter: [
slackAdapter({ token: process.env.SLACK_BOT_TOKEN! }),
discordAdapter({ webhookUrl: process.env.DISCORD_WEBHOOK_URL! }),
],
})// vite.config.ts
import { musVitePlugins } from '@datachef/mus/vite'
export default defineConfig({
plugins: [react(), ...musVitePlugins()],
})Production: run the pre-built mus-server Docker image alongside your app. No Node.js server to maintain:
services:
mus-server:
image: ghcr.io/datachefhq/mus-server:latest
environment:
- SLACK_BOT_TOKEN=${SLACK_BOT_TOKEN}MUS auto-fills name and email from your auth system via pluggable resolvers:
import { clerkResolver } from '@datachef/mus/resolvers/clerk'
<MusProvider config={{
...
userResolver: clerkResolver(),
}}>Built-in resolvers: stytchResolver, clerkResolver, auth0Resolver, nextAuthResolver. Or write your own: a resolver is just a React hook that returns { name, email }.
mus.datachef.co: configuration reference, adapters, resolvers, and server setup guides for Next.js / Express / Hono / Vite.
The component library is React (18 and 19). The server handlers and mus-server Docker image are framework-agnostic, so your backend can be anything.
Read CONTRIBUTING.md and open a PR. Issues and feature requests welcome.
MIT © DataChef HQ
