A native macOS menubar app that puts Apple Intelligence at your fingertips — no API keys, no cloud, no Ollama. Powered entirely by on-device inference via apfel.
Requires macOS 26 Tahoe (beta) and Apple Silicon. Apple Intelligence must be enabled on your device.
grapfel sits in your menubar. Click the icon (or press ⌘⇧Space from anywhere) to open a lightweight prompt window, type your request, hit Enter to send, and get a response from the on-device foundation model — instantly, privately, offline.
- no API keys — runs entirely on-device via Apple Intelligence
- no cloud — your prompts never leave your Mac
- no Ollama — uses Apple's own foundation model, not a third-party runtime
- fast — apfel's server mode keeps the model loaded; responses start in ~1 second
- persistent conversations — pick up exactly where you left off between sessions
| Requirement | Details |
|---|---|
| macOS | 26 Tahoe (beta) or later |
| Hardware | Apple Silicon (M-series) |
| Apple Intelligence | Must be enabled in System Settings |
| apfel | v1.3.3+ — see install below |
Download the latest release from the Releases page.
- Download the latest grapfel-X.Y.Z-macos26.zip from the Assets section of the release.
- Unzip and move
grapfel.appto/Applications. - Launch. The ✦ icon appears in your menubar.
grapfel is signed with a Developer ID certificate and notarized by Apple — no Gatekeeper prompt, no quarantine step required.
grapfel requires apfel to be installed and available on your PATH.
brew install apfelapfel is in homebrew-core as of v1.0.0. The tap (
brew tap Arthur-Ficial/tap) is no longer required.
Verify it works:
apfel "say hello"grapfel can be installed from a pre-built zip (see download above) or built from source.
-
Clone the repo:
git clone https://github.com/sfegette/grapfel.git cd grapfel -
Open the project in Xcode 26:
open grapfel.xcodeproj
-
Select your Mac as the run destination and press ⌘R.
The app will appear in your menubar as a ✦ icon.
Note: The global hotkey (⌘⇧Space) uses Carbon
RegisterEventHotKeyand does not require Input Monitoring permission.
| Action | How |
|---|---|
| Open / close | Click menubar icon, or press ⌘⇧Space from anywhere |
| Send prompt | Press Enter |
| Insert newline | Press ⌘+Enter |
| New conversation | Click the ✏ icon in the header (appears once a conversation is active) |
| Copy response | Click Copy at the bottom of any assistant message |
| Copy as code block | Right-click Copy → "Copy as Code Block" |
| Copy as plain text | Right-click Copy → "Copy as Plain Text" |
| Attach file | Click the paperclip button |
| Adjust options | Click the options disclosure group (temperature, max tokens, etc.) |
| Preferences | Press ⌘, or click the gear icon |
grapfel maintains full multi-turn conversation history. Each message you send includes the complete prior context so the model can refer back to earlier turns.
Conversation state is automatically saved to ~/Library/Application Support/grapfel/conversation.json — when you reopen the window (or relaunch the app), your conversation is restored exactly as you left it.
To start fresh, click the ✏ (compose) icon in the header. This clears the history and deletes the saved state.
Every assistant response has a Copy button at the bottom of its bubble. Tap to copy, or right-click for options:
| Option | What you get |
|---|---|
| Copy (tap) | Raw text — preserves Markdown syntax |
| Copy as Markdown | Same as above, explicitly labelled |
| Copy as Code Block | Response wrapped in ```markdown ``` — useful for embedding in docs |
| Copy as Plain Text | Markdown syntax stripped — clean text for pasting anywhere |
A brief Copied ✓ confirmation appears for 2 seconds after copying.
The options panel exposes the main apfel generation parameters:
| Option | Default | Notes |
|---|---|---|
| Temperature | 1.0 | Controls randomness (0.0–2.0) |
| Max tokens | 2048 | Maximum response length |
| Streaming | on | SSE streaming — token-by-token output as the model generates |
| JSON mode | off | Requests structured JSON output (response_format: json_object) |
| System prompt | — | Sets the system role message |
Token usage (prompt / completion / total) is shown beneath each response.
Permissive mode (disables content safety filtering) is a server-level setting — enable it in Settings → General. The server restarts automatically when toggled.
grapfel (menubar app)
└── launches apfel --serve on port 11434
└── wraps Apple's on-device foundation model
└── exposes OpenAI-compatible HTTP API at 127.0.0.1:11434/v1
grapfel manages the apfel --serve process lifecycle: starts it on launch, health-checks it, restarts on crash, and terminates it cleanly on quit. All communication is over localhost — nothing touches the network.
AppDelegate
├── GrapfelPanel (NSPanel subclass — Liquid Glass, borderless, canBecomeKey)
├── ApfelServerManager (actor — subprocess lifecycle)
├── ServerState (@Observable — propagates .starting/.running/.binaryNotFound/.startFailed to UI)
└── Carbon hotkey (⌘⇧Space, no Input Monitoring permission required)
ChatViewModel (@Observable @MainActor)
├── history: [ChatMessage] — full conversation context
├── send() — appends turns, calls API, saves to disk
└── clearHistory() — resets state and deletes saved file
ConversationView
├── MessageRow (user: right/.quaternary, assistant: left/purple tint)
├── MarkdownContent (fenced code blocks + AttributedString inline markdown)
└── CopyButton (tap = raw markdown; context menu = code block / plain text)
grapfel uses Sparkle for automatic updates. Right-click the ✦ menubar icon → Check for Updates… to check manually, or let it check in the background automatically.
- Global hotkey is not yet configurable — ⌘⇧Space is hardcoded; a settings UI is on the roadmap (#8).
- macOS 26 only — Apple Intelligence and Liquid Glass APIs require the macOS 26 SDK.
- Menubar icon + panel (Liquid Glass, GrapfelPanel)
- apfel server lifecycle management (start, health-check, crash-restart)
- Prompt → response via OpenAI-compatible API
- Options panel (temperature, max tokens, system prompt, etc.)
- Enter to send, ⌘+Enter for newline
- Global hotkey (⌘⇧Space, no Input Monitoring permission)
- Multi-turn conversation history with full context
- Conversation persistence (auto-save/restore across sessions)
- Markdown rendering (code blocks, bold, italic, inline code)
- Copy response (raw, code block, plain text)
- App icon (interim generated; final hand-crafted artwork pending)
- Build output to
build/Release/grapfel.app(Release config) - Release zip published to GitHub Releases (v0.1.0)
- Error UI for binary-not-found / server-start-failed (first-launch onboarding)
- SSE streaming (enabled — apfel 1.3.3)
- Sparkle auto-update (v0.1.3)
- Developer ID signed + notarized (v0.1.3)
- apfel version check + upgrade nudge (v0.1.3)
- Token usage display (v0.1.3)
- JSON mode (v0.1.3)
- Permissive mode in Settings (v0.1.3)
- Configurable hotkey in Settings (#8)
- Full test suite (#10)
- Final icon artwork (#9)
- apfel by Arthur-Ficial — the CLI/server that makes Apple Intelligence scriptable
- Built with SwiftUI + Swift 6 on macOS 26 Tahoe
MIT