{"id":"beautiful-chat","repo":"ABorakati/beautiful-chat","url":"https://github.com/ABorakati/beautiful-chat","name":"beautiful-chat","description":"Paseo plugin: a beautiful chat for OMP tools, reasoning, prompts, and tasks","categories":["productivity"],"platforms":[],"caveats":["Requires Paseo 0.8 or newer","Syntax highlighting runs on the daemon over a plugin RPC","Selection actions and the pointer glow are desktop and web only"],"images":["https://raw.githubusercontent.com/ABorakati/beautiful-chat/5afb2ee13a6384d44dff27eecf5e852bca099869/images/hero.png","https://raw.githubusercontent.com/ABorakati/beautiful-chat/5afb2ee13a6384d44dff27eecf5e852bca099869/images/thread.png","https://raw.githubusercontent.com/ABorakati/beautiful-chat/5afb2ee13a6384d44dff27eecf5e852bca099869/docs/images/tool-bash.png","https://raw.githubusercontent.com/ABorakati/beautiful-chat/5afb2ee13a6384d44dff27eecf5e852bca099869/docs/images/tool-read.png","https://raw.githubusercontent.com/ABorakati/beautiful-chat/5afb2ee13a6384d44dff27eecf5e852bca099869/docs/images/tool-image.png","https://raw.githubusercontent.com/ABorakati/beautiful-chat/5afb2ee13a6384d44dff27eecf5e852bca099869/docs/images/tool-edit.png","https://raw.githubusercontent.com/ABorakati/beautiful-chat/5afb2ee13a6384d44dff27eecf5e852bca099869/docs/images/tool-thinking.png","https://raw.githubusercontent.com/ABorakati/beautiful-chat/5afb2ee13a6384d44dff27eecf5e852bca099869/docs/images/tool-mcp.png"],"health":{"manifestValid":true,"hasReadme":true,"hasLicense":true,"hasTests":false,"hasTypecheckScript":true,"updatedRecently":true},"scannedAt":"2026-09-15T12:53:45.508Z","addedAt":"2026-09-15T13:31:08+03:00","version":"0.1.0","security":{"status":"passed","blockingFindings":0,"advisoryFindings":0,"scannedAt":"2026-09-15T12:52:08.853Z","commit":"5afb2ee13a6384d44dff27eecf5e852bca099869"},"license":"MIT","paseoVersionRequirement":">=0.8.0","manifest":{"id":"beautiful-chat","requirements":{"paseo":">=0.8.0"}},"repoMeta":{"stars":1,"defaultBranch":"main","pushedAt":"2026-09-15T10:44:57Z"},"owner":{"login":"ABorakati","avatarUrl":"https://avatars.githubusercontent.com/u/41518783?v=4"},"installNotesHtml":"<pre><code class=\"language-bash\">paseo plugin install ABorakati/beautiful-chat\n</code></pre>\n<p>The manifest requires Paseo <code>>=0.8.0</code>. Open <strong>Settings → Plugins → Beautiful Chat</strong> for the\naccent, fonts, frosted glass, and prompt bubble options.</p>\n<hr>","readmeText":"# Beautiful Chat\n\nA Paseo plugin that redraws the Oh My Pi (OMP) chat stream: tool calls, reasoning, prompts, approvals,\nand checklists. It replaces the host rendering of OMP timeline items with typed, syntax-aware cards\nthat follow the active Paseo theme.\n\n![A prompt, a tool call, a finished background job, and the reply that closes the turn](images/hero.png)\n\nEvery screenshot here is a capture of the real component, rendered by the harness in `.showcase/`.\n[One whole turn, top to bottom](images/thread.png) shows the cards in the order the timeline draws\nthem.\n\n## Install\n\n```bash\npaseo plugin install ABorakati/beautiful-chat\n```\n\nThe manifest requires Paseo `>=0.8.0`. Open **Settings → Plugins → Beautiful Chat** for the\naccent, fonts, frosted glass, and prompt bubble options.\n\n---\n\n## Tool calls\n\n### Shell and Git\n\nTerminal frame, Bash syntax, exit code, duration, and the Git brand mark. A command that prints\nnothing says so rather than showing an empty panel.\n\n![Shell and Git tool calls](docs/images/tool-bash.png)\n\n### Read\n\nThe file's own language logo, a wrapped path, line numbers, and a copy button. The path is a link:\npressing it shows the file in the machine's file manager.\n\n![Read tool call](docs/images/tool-read.png)\n\n### Images\n\nA read of a `.png` carries no bytes through the timeline, so the host draws it as an empty code\nblock with a language badge. This card draws the file instead: a picture mark, the path as a link,\nthe pixel size and file size read from the header, and an eye control that hides the thumbnail. The\nbytes come from the plugin's own daemon-side RPC (`file.image`), which is the only side that can\nreach the file; PNG, JPEG, GIF, WebP, AVIF, BMP, ICO and SVG are recognised, and anything past\n3 MB reports its size rather than inlining a data URI.\n\n![Image read](docs/images/tool-image.png)\n\n### Edit\n\nDiff rendering where adjacent removed and added rows join into one rounded block, and only the\nmarker column carries the red or green.\n\n![Edit tool call](docs/images/tool-edit.png)\n\n### Reasoning tool\n\nLive thinking text, a token badge, and numbered steps.\n\n![Thinking tool call](docs/images/tool-thinking.png)\n\n### MCP\n\nServer badge, transport, input parameters, and the response payload, each syntax-highlighted.\n\n![MCP tool call](docs/images/tool-mcp.png)\n\n### Eval\n\nOne card per kernel cell: the source that ran, then the text it printed.\n\n![Eval tool call](docs/images/tool-eval.png)\n\n### Ask\n\nOption cards with the recommended badge, the chosen answer marked, and a typed reply labelled as\ntyped rather than shown as a selection.\n\n![Ask tool call](docs/images/tool-ask.png)\n\n### Task\n\nSubagent name, type, model, and the delegated instructions.\n\n![Task tool call](docs/images/tool-task.png)\n\n### Hub\n\nEvery `hub` op is mapped: `start`, `stop`, `restart`, `ps`, `logs`, and `describe` render the\nprocess card with its launch line, readiness, and recent output; `send`, `wait`, `inbox`, and\n`list` render the message card; `jobs` and `cancel` render the job snapshot. The cards report;\nthey carry no buttons, because a plugin cannot restart or cancel anything.\n\n![Hub tool calls](docs/images/hub.png)\n\n### Paseo tools\n\nPaseo's own mark leads the card, and the created agent's provider carries its brand mark.\n\n![Paseo tool call](docs/images/paseo.png)\n\n---\n\n## Stream components\n\n### Reasoning trace\n\nA collapsible trace with a connected step rail, per-step duration, and a token total.\n\n![Reasoning trace](docs/images/reasoning.png)\n\n### Checklist\n\nPhase name, per-task status, durations, and a blocked task with its reason.\n\n![Checklist](docs/images/tasks.png)\n\n### Approval card\n\nRisk classification, the exact command, target path, working directory, and the approve or deny\nactions the host owns.\n\n![Approval card](docs/images/approval.png)\n\n### Prompt bubble\n\nThe authored turn on a raised theme surface with a square tail, a copy button, and the turn's token\nusage.\n\n![Prompt bubble](docs/images/user.png)\n\n### Syntax block\n\nShared by every card that shows code: language detection from the path, line numbers, diff tints,\nDevicon brand marks, and the file-manager link.\n\n![Syntax block](docs/images/syntax.png)\n\n---\n\n## Settings\n\n![Settings screen](docs/images/settings.png)\n\n| Setting                | Effect                                                             |\n| ---------------------- | ------------------------------------------------------------------ |\n| Accent colour          | Follow the Paseo theme, or pick Jade, Violet, Amber, or Rose.      |\n| Interface font         | Embedded Inter, or the system interface face.                      |\n| Code glyphs            | Iosevka with ligatures, or literal glyphs.                         |\n| Frosted glass          | Blur card surfaces, or paint them solid.                           |\n| Enhanced prompt bubble | Off hands prompts back to Paseo, whose bubble shows pasted images. |\n\n---\n\n## Opening files\n\nA file name in a read, write, edit, or code block is a link. Pressing it calls the plugin's own\ndaemon-side RPC (`file.reveal`), which resolves the path against the agent's working directory and\nasks the platform shell to show it:\n\n| Platform | Behaviour                                              |\n| -------- | ------------------------------------------------------ |\n| Windows  | `explorer.exe /select,<file>` selects the file.        |\n| macOS    | `open -R <file>` selects the file in Finder.           |\n| Other    | `xdg-open <directory>` opens the containing directory. |\n\nA directory path opens that directory. A path the daemon cannot stat does nothing.\n\n## Unmapped output\n\nA tool the plugin has no typed card for still shows its output in the terminal frame, and a call\nthat printed nothing says so. No card renders an empty panel.\n\nThe link cannot open Paseo's own file editor: see the first limitation below.\n\n---\n\n## Plugin SDK limitations found while building this\n\nMeasured against `@getpaseo/plugin` 0.8.0 and the Paseo 0.8.0 desktop build. Each entry names the\nevidence and the workaround this plugin uses.\n\n1. **No file navigation.** Timeline renderer props are exactly `{agentId, theme, host, layout,\ntimestamp, item}`, and plugin navigation offers only `openSettings`, `openSurface`,\n   `openWorkspacePanel`, `openAgentPanel`, `openAgent`, and `openWorkspace`. The host's own file tab\n   target (`{kind:\"file\", path}`, reachable in-app through `?open=file:<path>`) is not exposed, and\n   the `paseo://` scheme only carries agent deep links. Workaround: a daemon-side RPC that reveals\n   the path in the operating system's file manager.\n2. **Transformers see a stripped item.** The app maps its stream item to the plugin item before any\n   transformer runs, and a user message keeps only `text`, `messageId`, and `clientMessageId`. Pasted\n   images never reach plugin code, and the daemon timeline row stores the same item, so a server RPC\n   cannot recover them either. Workaround: the **Enhanced prompt bubble** setting returns prompts to\n   the host.\n3. **Interception is all or nothing.** A transformer replaces the host item completely. There is no\n   way to decorate an item or keep host affordances that the plugin does not reimplement. Returning\n   `undefined` is the only opt-out.\n4. **Transform results are cached per item.** Changing a preference does not re-run transformers for\n   items already on screen. New items follow the change; existing ones need a reload.\n5. **Renderers get no workspace.** Props carry `agentId` only, so `cwd` and `workspaceId` need a\n   second lookup through `useAgent`.\n6. **Token usage is live-only.** Usage is not persisted on timeline items, so a turn this client did\n   not observe live shows no figures.\n7. **RPC names are validated late.** The host requires `^[a-z][a-z0-9._-]*$`. A camelCase name such\n   as `revealPath` typechecks, then fails the whole plugin at install or reload with\n   `Invalid plugin RPC method`.\n8. **The React Native runtime module is a stub in the package.** `@getpaseo/plugin/client/react-native`\n   ships as `export {}`; the host injects the implementations. Bundling or testing plugin UI outside\n   Paseo needs a shim, which is what `.showcase/shims` provides.\n9. **The theme carries six colours.** `PluginTheme` exposes `surface0`–`surface2`, `border`,\n   `foreground`, `foregroundMuted`, `accent`, `accentForeground`, and three status colours. Every\n   other surface, including code backgrounds and diff tints, must be derived with alpha; that is what\n   `client/components/theme-tokens.ts` exists for.\n10. **No CSS escape hatch.** React Native styles drop unknown keys, so `backdrop-filter` is\n    impossible through the style API. Frosted glass is a hand-injected `<style>` rule matched by a\n    data attribute.\n11. **No font registration.** Faces are embedded as data URIs in an injected `@font-face` rule, and\n    every surface needs a wrapper that escapes the host's own font cascade.\n12. **A closed module allowlist, and no SVG renderer.** Plugin client code may import only\n    `react`, `react/jsx-runtime`, `react-native`, `@tanstack/react-query`, `zod`,\n    `@getpaseo/plugin`, `@getpaseo/plugin/client`, `@getpaseo/plugin/client/react-native`, and\n    `@getpaseo/plugin/client/ui`. Anything else throws\n    `Module \"x\" is not available in plugin client code` when the bundle loads, so\n    `react-native-svg` and `lucide-react-native` are out of reach. Lucide icons still work,\n    because the host renders them: `Icon` from `@getpaseo/plugin/client/react-native` takes any\n    Lucide name. Brand marks are not in Lucide, and React Native's `<Image>` decodes PNG, JPEG,\n    GIF, and WebP but never SVG, so a data-URI SVG renders on web and stays blank on iOS and\n    Android. Those marks ship as PNG rasters in `client/components/mark-bitmaps.ts`.\n13. **Settings are host-scoped only.** `defineSettings` rejects any scope other than `host`, so\n    per-workspace or per-agent presentation settings are impossible. This plugin keeps presentation\n    preferences in client storage instead.\n\n---\n\n## Project structure\n\n```text\nbeautiful-chat/\n  paseo-plugin.json          # Manifest: id and Paseo requirement\n  index.client.tsx           # Timeline transformers, renderers, settings screen\n  index.server.ts            # Daemon-side RPCs (file.reveal)\n  shared/\n    contracts.ts             # Data contracts shared by client and server\n    file-rpc.ts              # file.reveal contract\n  client/\n    live-renderers.tsx       # Timeline item to component mapping\n    settings-page.tsx        # Settings screen\n    preferences.ts           # Client-side presentation preferences\n    components/              # Cards, syntax block, glyphs, motion, theme tokens\n      mark-bitmaps.ts        # GENERATED PNG rasters of every brand mark\n      devicon-data.ts        # Vendor SVG sources, read only by the generator\n      lobe-marks.ts          # Vendor SVG sources, read only by the generator\n  .showcase/                 # Offline harness used to capture the screenshots\n  docs/images/               # Screenshots in this README\n```\n\n## Development\n\n```bash\nnpm install\nnpm run typecheck\npaseo plugin reload beautiful-chat\n```\n\nRebuild the screenshots after a visual change:\n\n```bash\nesbuild .showcase/showcase.tsx --bundle --outfile=.showcase/showcase.js --jsx=automatic \\\n  --alias:react-native=react-native-web \\\n  --alias:@getpaseo/plugin/client/react-native=./.showcase/shims/plugin-react-native.tsx\n```\n\nThen serve `.showcase/` and capture each `#shot-*` element.\n\n## License\n\nMIT\n"}