← All work
Applied AI · macOS

Jellybean

A native macOS floating assistant: a red jellybean that expands into a chat backed by your own on-prem household agent, no third-party LLM.

A native macOS floating assistant for the Titan household agent — a red jellybean that lives on your screen, expands into a chat, and answers from your own on-prem AI.

Jellybean is a SwiftUI/AppKit menu-bar app. A draggable bean floats above everything; click it and it morphs open into a chat backed by the Titan household agent (a local Qwen3-8B model plus a fleet of knowledge/graph/vision runtimes running on your GPU host). Nothing goes to a third-party LLM — the brain is yours.

   ●  floating bean ──click──▶  chat unfurls from the bean
   │                            (the bean becomes the send button)
   └─ menu bar item · J global hotkey

What it does

  • Chat with your household agent — recall facts, run calculations, read files, fetch links.
  • Knowledge base browser — search and read everything the agent knows, organized by category (general · local · household · personal · workload · project), and tag items as context that ride along on your next message.
  • Drop / paste anything — images (described via vision), files (ingested), links (fetched), text (into the field).
  • Expressive bean — the floating icon changes color, glow, and a status tag to show state (idle · thinking · uploading · done · error), with an unread badge + TL;DR peek when closed.
  • Device control (in progress) — calendar, reminders, alarms, files, Shortcuts, and a skills system, executed natively on the Mac with per-action confirmation and backups. See docs/ARCHITECTURE.md.
  • Live, persisted settings — tune the animation/appearance from a Settings window; saved to ~/.config/jellybean/config.json.

Requirements

  • macOS 14+ (built/tested on macOS 26, Apple Silicon)
  • Swift 6 / Xcode 16+
  • SSH access to the Titan host as the titan alias (~/.ssh/config), and the titan-node repo at ~/Projects/titan-node (the app shells its CLI). Override with TITAN_CLI / TITAN_SSH_HOST.

Build & run

cd mac
swift run                 # dev: launches the app directly
# or package a proper accessory .app:
./build-app.sh            #  mac/Jellybean.app  (LSUIElement, ad-hoc signed)
open ./Jellybean.app

The app has no Dock tile (it's an accessory). It appears as the floating bean (bottom-right) and a bean in the menu bar.

Using it

Action How
Open / close chat Click the bean · menu-bar bean · J (global) · Esc to close
Move the bean Drag it
Send Return, or click the bean-turned-send-button
Attach Paperclip, drag-drop, or paste an image/file
Browse knowledge Books icon in the input, or right-click bean Knowledge base
Tag context Check items in the KB browser they appear as chips above the input
Settings Right-click bean Settings (live; persisted)
Edit C / V / X / A / Z all work; reply text is selectable

How it connects

The app talks to the agent through the titan-node CLI over SSH (AgentClient shells titan.sh agent prompt --tools). The agent loop runs on the host (where the runtimes live); the Mac is the UI and the "hands" for device actions. See docs/ARCHITECTURE.md for the full picture and the host-side integration docs (titan-node, docs/jellybean-integration.md).

Project layout

mac/
  Package.swift            Swift package (executable, macOS 14)
  build-app.sh             package the binary into Jellybean.app
  make-icon.sh             regenerate both icons from icon/jellybean.svg
  Info.plist               LSUIElement accessory app
  icon/
    jellybean.svg          the bean — single source of truth for all icons
    AppIcon.icns           app/Dock icon (generated)
  Sources/Jellybean/
    main.swift             NSApplication bootstrap (accessory policy)
    AppShell.swift         AppDelegate, panels, menu bar item, command bar, hotkey, windows
    IconView.swift         the floating bean: states, doze-to-dot, beansend morph
    ChatView.swift         the chat UI: welcome, bubbles, input, paste/drop, confirm card
    ChatViewModel.swift    chat state, send loop, fast-path, KB context, device handling
    DeviceExecutor.swift   native device actions (calendar/reminders/files/automation/skills)
    DeviceBridge.swift     device protocol parsing + local risk derivation
    AgentClient.swift      Process bridge to titan.sh (chat / device / kb); host upload
    KnowledgeBase.swift    KB model + master-detail browser (search, categories, edit)
    CommandBar.swift       Spotlight-style launcher
    AppSettings.swift      live tunables + ~/.config persistence + Settings window
    MarkdownText.swift     block markdown renderer (headings, lists, code, inline)
    PeekView.swift         TL;DR card that pops from the bean on a reply
    Models.swift           ChatMessage
    Resources/jellybean.png  the floating bean (generated)
docs/ARCHITECTURE.md       system design
CLAUDE.md                  dev guide (auto-loaded by Claude Code)

Changing the bean

The bean is one SVG. Edit mac/icon/jellybean.svg and run ./make-icon.sh to regenerate the floating bean (Resources/jellybean.png) and the app icon (icon/AppIcon.icns).

This is a fully native app. The earlier Electron/React build has been removed.

License

Personal project — © Zach Shallbetter.