A Spotlight-style quick-ask panel for macOS. One global shortcut, one input, any model from any provider using your own API keys — including local ones.
Press ⌥Space anywhere. A floating bar appears over whatever you are working in, without switching away from it. Ask, read the streamed answer in place, press Esc, carry on.
Claiming ⌥Space globally means it no longer inserts a non-breaking space while the app is running. Change the shortcut in settings if you need that back.
Download chat-island 0.1.0
— one universal .dmg, 9.5 MB, Intel and Apple Silicon, macOS 13 or later.
Check the file you got against the one that was published:
shasum -a 256 ~/Downloads/chat-island_0.1.0_universal.dmgdcc1544fde44d1279827045d99c1a4c4898ceed59e083951ef8659be172515ce
The build is neither signed nor notarised, so macOS blocks it the first time. That warning is expected, and clearing it is a one-off.
- Open the DMG and drag chat-island onto Applications.
- Launch it from Applications. macOS refuses, with either "chat-island" cannot be opened because Apple cannot check it for malicious software or "chat-island" is damaged.
- Open System Settings ▸ Privacy & Security, scroll to Security, and press Open Anyway on the row naming chat-island. Confirm with Touch ID, then press Open in the dialog that follows.
The button only appears after a blocked launch, and right-click ▸ Open is not an alternative — macOS 15 removed that path. If the damaged wording persists, strip the quarantine flag by hand:
xattr -dr com.apple.quarantine /Applications/chat-island.appThen press ⌥Space and add an API key under Providers.
| Permission | How it is granted | Without it |
|---|---|---|
| Accessibility | By hand, once | Selecting text before asking silently sends nothing |
| Microphone | Prompted on the first recording | The mic button does nothing |
| Documents, Desktop, Downloads | Prompted per folder, and each action still needs your approval in the app | File tools cannot read or write there |
macOS shows its Accessibility dialog only once per app and never again, so the app also opens System Settings ▸ Privacy & Security ▸ Accessibility the first time it needs the grant. Add chat-island there and switch it on.
A grant is bound to the exact build that received it. After replacing the app with a differently signed one, macOS keeps matching against the old code requirement and the switch stops taking effect; deleting the record and granting it again fixes that:
tccutil reset Accessibility com.chatisland.appOne adapter speaks the Anthropic Messages API; a second speaks the OpenAI
/chat/completions format, which covers everything else. Adding a vendor that
speaks an existing protocol is a row in
src-tauri/src/adapters/providers/catalog.rs — no new code.
| Provider | Key required |
|---|---|
| Anthropic | yes |
| OpenAI | yes |
| DeepSeek | yes |
| GLM (Z.ai) | yes |
| Kimi (Moonshot) | yes |
| OpenRouter | yes |
| Groq | yes |
| xAI | yes |
| Google Gemini | yes |
| Mistral | yes |
| Qwen (Alibaba) | yes |
| Perplexity | yes |
| Together AI | yes |
| Ollama | no — http://localhost:11434 |
| LM Studio | no — http://localhost:1234 |
| Anything else | add a custom OpenAI-compatible base URL in settings |
Custom entries live in settings.json, and a custom id can never shadow a
built-in provider. Model lists are fetched live from each provider's /models
endpoint and cached for 24 hours, falling back to the catalog's seed list.
Keys go into the macOS Keychain under the service com.chatisland.app, and
are read only by the Rust process, only when building an outbound request to the
provider you selected.
The webview never sees a key. There is no IPC command that returns one — the
frontend only ever sends a providerId. Tests pin this.
Inspect or revoke them yourself:
security find-generic-password -s com.chatisland.app
security delete-generic-password -s com.chatisland.app -a anthropicIt does not read sessions, cookies, or Keychain items belonging to any other installed application, nor inspect which applications are installed.
| Key | Action |
|---|---|
| ⌥Space | Show / hide the panel (rebindable) |
| Enter | Send |
| ⇧Enter | Newline |
| Esc | Stop the stream → close the drawer → hide the panel |
| ⌘N | Clear and start a new question |
The chip on the left of the bar opens the model list: filter by name, pick any model from any configured provider.
Pick a transcription provider and model under Voice in settings — OpenAI,
Groq, and Mistral ship one, and any other endpoint that implements
/audio/transcriptions can be typed in by hand. The mic button then records
(up to five minutes) and drops the transcript into the input.
Audio is uploaded by the Rust process using the key already stored for that provider; the recording is never written to disk.
Needs Rust (https://rustup.rs) and Xcode Command Line Tools.
npm install
rustup target add x86_64-apple-darwin # the other half of the universal build
npm run tauri dev
npm run package # universal .app + DMGnpm run package writes to src-tauri/target/universal-apple-darwin/release/bundle
and prints the SHA-256. Build for one architecture with
CHAT_ISLAND_TARGET=aarch64-apple-darwin npm run package.
npm run typecheck # strict TS, no `any`
cargo test --manifest-path src-tauri/Cargo.tomlDependencies point inward only: infrastructure → adapters → application → domain.
src-tauri/src/
domain/ pure Rust — no serde, tauri, reqwest, or rusqlite
application/ use cases behind port traits; no framework types
adapters/ Keychain, SQLite, HTTP providers, macOS system access
infrastructure/ the only place Tauri appears; composition root in container.rs
src/
domain/ types only
application/ hooks as view models
adapters/ tauriClient.ts — the only file importing @tauri-apps/*
ui/ components
The domain layer holds no serde derives; everything crossing IPC is mapped in
infrastructure/dto.rs, which keeps serialisation out of the business types.
There is no Dock icon and no window until you press the shortcut — the app runs
with ActivationPolicy::Accessory, and the panel's non-activating style mask is
what stops it stealing focus.
| What | Where |
|---|---|
| Conversations | ~/Library/Application Support/com.chatisland.app/chat-island.sqlite3 |
| Settings | ~/Library/Application Support/com.chatisland.app/settings.json |
| API keys | macOS Keychain (com.chatisland.app) |
Developed and tested on macOS 26, Apple Silicon. The Intel half of the universal binary is compiled but has not been run on Intel hardware.
Releases are unsigned and not notarised; both need a paid Apple Developer account. Signing with any certificate — including the free Apple Development one — is still worth it while developing, because an unsigned bundle gets a new code identity on every compile and macOS drops the Accessibility grant with it:
security find-identity -v -p codesigning # list the names
export CHAT_ISLAND_SIGN_IDENTITY="Apple Development: …"
npm run packageTauri signs the app before packaging it, so the image never carries an unsigned
copy. Changing identity invalidates grants given to earlier builds: macOS stores
the code requirement alongside the permission, tccd logs Failed to match existing code requirement, and removing the row in System Settings only
recreates it against the same stale requirement. tccutil reset Accessibility com.chatisland.app deletes the record; grant it once more afterwards and every
build signed with the same certificate keeps it.
MIT — see LICENSE, © 2026 buchmark.
| You may | You must | You get no |
|---|---|---|
| Use it, privately or commercially | Keep the copyright line and the licence text in copies and in substantial portions of the source | Warranty — the software ships "AS IS" |
| Read, modify, and fork the source | Liability on the author for any damage it causes | |
| Redistribute, sublicense, or sell it | Right to the chat-island name or logo | |
| Keep your own changes closed | Express patent grant |
Publishing your changes is not required; this is not a copyleft licence. The one real obligation is carrying the licence text along.
Two things in this repository are not covered by it: the provider brand icons in
src/ui/icons/brands/, which keep their own licence, and the provider names
themselves, which are other companies' trademarks. Both are set out in
THIRD-PARTY-NOTICES.md.