An invisible desktop AI overlay for Claude, GPT, Gemini, and local models.
Features · Quick start · Hotkeys · Providers · Architecture · Roadmap · Contributing
Penumbra is a translucent always-on-top desktop overlay that puts a multi-model AI assistant one keystroke away. Snap a screenshot, drop in an audio file, or just chat — and get an answer from Claude, GPT, Gemini, or a model running on your own machine. The window is invisible to screen sharing on macOS and Windows by default, so it stays out of your demos and recordings.
Inspired by free-cluely and rebuilt from scratch with a provider-agnostic architecture, a clean pnpm monorepo, encrypted key storage, and first-class Claude support.
- Truly invisible. Frameless translucent window, always on top, hidden from screen sharing (
setContentProtection), no taskbar entry. - Multi-provider, no lock-in. Anthropic Claude, OpenAI GPT, Google Gemini, Ollama, and any OpenAI-compatible endpoint — OpenRouter, Groq, Together, Fireworks, LM Studio, LocalAI, vLLM, llama.cpp.
- Vision built in.
Cmd/Ctrl + Hcaptures the screen, sends it to a vision-capable model, and streams the answer back. - Persistent chat history. Every turn is saved to a local SQLite database. Quit, restart, pick up where you left off. Browse, search, rename, delete past conversations.
- Local-first by default. All app state lives in a single SQLite file at
userData/penumbra.db. API keys are encrypted via OS keychain. Nothing leaves your machine except your prompts to the provider you configured. - Pluggable models. Point it at Ollama or LM Studio and Penumbra never touches the cloud.
- Global hotkeys. Toggle, capture, focus, settings. All remappable.
- Browser dev mode. The Vite dev URL works in any browser for fast UI iteration — chat persists to
localStoragethere.
![]() Empty state — hotkey crib sheet |
![]() Settings — pick any provider |
git clone https://github.com/siri1410/penumbra.git
cd penumbra
corepack enable
pnpm install
pnpm devOn first launch the overlay appears in the top-right of your primary display. Open Settings (Cmd/Ctrl + ,), pick a provider, paste an API key, and start asking.
Prefer the browser?
pnpm devalso serves the UI at http://localhost:5180. Chat works there withlocalStorage-backed config. Screenshots and global hotkeys are Electron-only.
| Action | macOS | Windows / Linux |
|---|---|---|
| Toggle window | ⌘ B |
Ctrl + B |
| Capture & ask | ⌘ H |
Ctrl + H |
| Focus chat | ⌘ J |
Ctrl + J |
| Open settings | ⌘ , |
Ctrl + , |
Remap any of them in Settings.
| Provider | Vision | Streaming | API key | Notes |
|---|---|---|---|---|
| Anthropic (Claude) | ✅ | ✅ | ✅ | claude-opus-4-7, claude-sonnet-4-6, claude-haiku-4-5 |
| OpenAI | ✅ | ✅ | ✅ | gpt-4o, gpt-4.1, o4-mini |
| Google Gemini | ✅ | ✅ | ✅ | gemini-2.0-flash, gemini-2.0-flash-thinking-exp |
| Ollama | ✅¹ | ✅ | — | Default URL http://localhost:11434. Try llama3.2-vision, llava. |
| OpenAI-compatible | ✅¹ | ✅ | opt. | OpenRouter, Groq, Together, Fireworks, LM Studio, LocalAI, vLLM… |
¹ Vision requires the underlying model to support image input.
- Implement
Providerinpackages/providers/src/providers/<name>.ts. - Register a descriptor +
createProvidercase inpackages/providers/src/registry.ts. - Open a PR. See
anthropic.tsfor the canonical example.
If the service speaks the OpenAI wire format (/v1/chat/completions), the existing OpenAI-compatible adapter probably handles it — point it at the base URL and you're done.
Penumbra is a pnpm monorepo:
penumbra/
├── apps/
│ └── desktop/ Electron + React 18 + Vite + Tailwind overlay app
└── packages/
├── core/ Chat session, system prompts, default config
├── db/ SQLite schema + repos (better-sqlite3)
├── providers/ Unified Provider interface + 5 adapters
└── types/ Shared TypeScript types (no runtime deps)
┌────────────────────┐ IPC (contextIsolation) ┌────────────────────┐
│ Electron renderer │ ◄────────────────────────► │ Electron main │
│ React + Tailwind │ │ hotkeys / capture │
│ ChatSession ──────┼─── streams ────────────────│ safeStorage │
└──────────┬─────────┘ └─────────┬──────────┘
│ HTTPS │
▼ ▼
┌──────────────────────────────────────────────────────────────┐
│ Provider adapter (Anthropic / OpenAI / Gemini / Ollama / │
│ OpenAI-compatible) — streams ChatChunk back to ChatSession │
└──────────────────────────────────────────────────────────────┘
All adapters share one Provider interface:
interface Provider {
readonly id: ProviderId;
readonly supportsVision: boolean;
chat(messages: ChatMessage[], opts?: ChatOptions): AsyncIterable<ChatChunk>;
}That's the entire extension surface.
Penumbra is built so your conversations stay yours.
- Single local database. All conversations, messages, configuration, and provider settings live in one SQLite file at
userData/penumbra.db. Quitting and re-launching restores the most recent conversation; the drawer (≡) lists everything. - Encrypted API keys. Keys never go into the SQLite file. They live in
userData/secrets.bin, encrypted via ElectronsafeStorage(macOS Keychain, Windows DPAPI, Linux libsecret where available). - No telemetry, no phone-home. The only outbound traffic is your prompts going to the provider you configured. Penumbra itself calls nothing.
- Local models supported. Point at Ollama, LM Studio, vLLM, or llama.cpp and nothing leaves your machine.
- Delete on demand. Drawer → kebab → Delete removes a conversation and cascades to its messages. "Delete all" in the drawer footer nukes everything.
- Portable. The whole DB is one file — back it up, sync it, inspect it with any SQLite tool.
Userdata locations:
- macOS:
~/Library/Application Support/@penumbra/desktop/- Windows:
%APPDATA%\@penumbra\desktop\- Linux:
~/.config/@penumbra/desktop/
- Whisper-based local audio transcription
- Region-select screenshot (don't grab the whole display)
- Plugin API for custom tools / actions
- Conversation history & search
- Multi-window workspaces
- Linux Wayland screenshot pipeline
- Tool use / function calling
See issues for what's actively being worked on.
PRs welcome — especially new provider adapters. Read CONTRIBUTING.md and the Code of Conduct.
Found a security issue? Please report it privately, not as a public issue.
MIT © Siri Y


