Kotoba Libre turns LibreChat into a focused Mac app.
The goal is simple: make LibreChat feel like a first-class desktop tool instead of a tab you keep losing. Kotoba Libre gives you a Spotlight-style command bar, voice entry, fast preset recall, and native window controls in a small macOS wrapper built with Swift, AppKit, SwiftUI, and WebKit.
LibreChat is powerful, but the browser workflow is easy to interrupt. Kotoba Libre keeps your instance close at hand, makes your favorite agents instantly recallable, and gives you dedicated shortcuts for typing, speaking, or showing the full app window without breaking flow.
- Spotlight-style launcher that is always one shortcut away
- Dedicated voice mode with animated listening state and Apple speech transcription
- Separate show/hide window shortcut for bringing the main app forward without opening the launcher
- Fast saving of agents and model links as presets so you can recall them in seconds
- Native-feeling experience around a live WebKit session, without the usual browser-tab reload dance, and with a small app footprint
- Menu bar only, Dock only, or hybrid presence modes depending on how visible you want the app to be
- Native onboarding, settings, popup handling, deep links, notifications, and Dock integrations tailored for LibreChat
Download the latest build from the GitHub Releases page.
Kotoba Libre currently ships as an unsigned, non-notarized macOS app. That means macOS will likely warn you the first time you open it. This is expected for the current release flow.
- Download
Kotoba Libre-unsigned.dmgfrom the latest release. - Drag
Kotoba Libre.appinto/Applications. - Open the app once.
- If macOS blocks it, Control-click the app in Finder, choose
Open, and confirm the prompt. - If macOS still refuses to launch it, open
System Settings > Privacy & Security, find the blocked-app message for Kotoba Libre, and clickOpen Anyway. - If the quarantine flag still sticks, run:
xattr -dr com.apple.quarantine "/Applications/Kotoba Libre.app"- macOS 26+
Kotoba Libre opens a floating Spotlight-like bar from a global shortcut, stays on top while you choose an agent or type a prompt, and launches into LibreChat only when you submit.
Voice mode uses its own shortcut and its own launcher surface. It starts listening immediately, shows live animated feedback, and sends the finished transcript to the selected agent when you trigger the shortcut again.
You also get a dedicated shortcut for the main window itself. Use it when you want the full LibreChat interface right away, then hide it again with the same shortcut when you are done.
Kotoba Libre now adds a broader layer of Mac-native behavior around the embedded LibreChat session:
- Background responses can raise a system notification once they cross the long-response threshold you set in Settings
- Unread background completions increment the Dock badge and bounce the Dock icon
- The main app menu includes
Cmd+Nfor a new chat,Cmd+[andCmd+]for history,Cmd+Kfor message search, andEscapefor stop generating - Dragging one file onto the Dock icon opens a new chat and attaches it
- The main window title tracks the current chat title instead of staying static
When you are on an agent detail page inside LibreChat, Kotoba Libre can save that agent directly into the launcher list. It can also detect compatible model URLs and save them as Link presets, so the things you use most stay easy to recall.
Kotoba Libre keeps the desktop shell native and lightweight. Launcher interactions, settings, and window management happen in native macOS UI, while the embedded LibreChat session stays in place so your workflow avoids the usual browser-tab reload dance and the weight of a big cross-platform runtime.
- Swift 6.2
- macOS 26+
- Swift Package Manager
- AppKit app lifecycle and window management
- SwiftUI with native Glass effects for onboarding, settings, sheets, and launcher UI
- WebKit for the embedded LibreChat experience
- GitHub Actions for unsigned release automation
.
|-- Package.swift
|-- Sources
| |-- KotobaLibreApp
| |-- KotobaLibreCore
| `-- KotobaLibreSelfTest
|-- docs
| |-- architecture.md
| |-- development.md
| |-- release.md
| `-- plans
|-- scripts
| |-- build-app.sh
| |-- create-unsigned-dmg.sh
| |-- ci/semver-bump.sh
| `-- ci/validate-version.sh
`-- VERSION
Sources/KotobaLibreAppNative macOS executable. Owns the app lifecycle, windows, onboarding flow, settings UI, shortcut registration, and embeddedWKWebView.Sources/KotobaLibreCoreShared models and business logic: settings, preset normalization, deep links, URL validation, host restriction, import/export, and storage helpers.Sources/KotobaLibreSelfTestRunnable regression suite for core behavior in environments whereswift testis not available.
Build the project:
swift buildRun the self-test suite:
swift run KotobaLibreSelfTestRun the native GUI smoke test against an isolated temporary app-data directory:
swift run KotobaLibreApp --smoke-testLaunch the app directly from SwiftPM:
swift run KotobaLibreAppBuild the distributable app bundle and unsigned artifacts:
./scripts/build-app.shEnable popup-based passkey and security-key support for specific relying-party domains:
KOTOBA_ASSOCIATED_DOMAINS="chat.example.com,login.example.com" ./scripts/build-app.shThose entries are normalized to webcredentials: entitlements at packaging time. They only help when the LibreChat login flow opens in a popup that Kotoba Libre can route through its popup and browser-backed auth handling, including the default-on setting that lifts external-host login redirects into a separate app window instead of the external browser.
If your LibreChat login flow requires a passkey or FIDO or security key and stays inside the main embedded Swift window, Kotoba Libre does not support that flow yet. The supported path today is for the login flow to open in a popup, either directly from the site or via the Instance Settings option that opens external login redirects in a separate Kotoba Libre window.
Generated artifacts:
dist-artifacts/Kotoba Libre.appdist-artifacts/Kotoba Libre-unsigned.dmgdist-artifacts/Kotoba Libre-unsigned-app.zip
If no settings exist, the main window opens a four-step onboarding flow:
- Start with a welcome screen that explains Kotoba Libre as a macOS wrapper for LibreChat web apps
- Enter the LibreChat base URL
- Review optional voice permissions
- Confirm the setup and open LibreChat
The onboarding window opens as a compact wizard with focused steps, product context up front, inline URL validation, and default keyboard actions so first-run setup stays quick without needing an internal scroll area.
After setup completes, Kotoba Libre saves configuration, enables the app-wide shortcuts, and opens the main web view in a 900x660 default window.
The settings window includes tabs for:
- Agents
- Settings
- System
- Shortcuts
- About
The native settings, onboarding, add-agent sheet, and launcher surfaces use the recent macOS Glass APIs so the desktop chrome stays visually consistent across the app.
The settings UI warns before you leave a tab with unsaved changes.
When the embedded web view is on an agent detail page, the titlebar button can save that agent directly into the launcher list. The same button also detects /c/new model URLs such as ...?endpoint=anthropic&model=claude-opus-4-6 and offers to save them as Link presets.
From the System tab, users can also choose whether Kotoba Libre appears:
- In both the Dock and the menu bar
- Only in the Dock
- Only in the menu bar
When the menu bar item is enabled, it includes actions for opening Settings, showing the LibreChat window, and quitting the app.
The Shortcuts tab manages three separate shortcuts:
- Text launcher, which defaults to
Ctrl+Option+Space - Voice launcher, which defaults to
Ctrl+Option+V - Show app window, which defaults to
Ctrl+Option+K
The System tab also includes microphone and speech-recognition permission status, debug logging, and a destructive reset action that clears config and returns the app to onboarding.
The System tab also lets users decide whether long background responses should raise a system notification, and how many seconds a response must run before it counts as long.
When host restriction is enabled and you change the configured LibreChat instance to a different host, Kotoba Libre re-validates saved agents, offers an export step first, and removes any incompatible agents after you confirm the change.
The launcher is a floating panel that:
- Opens with the configured global shortcut after onboarding is complete
- Stays in front by itself instead of surfacing the main LibreChat window until a launch is submitted
- Lets the user pick an agent from a styled glass selector
- Passes prompt text into LibreChat URLs
- Falls back gracefully when no instance or presets are configured
Voice mode adds a second floating launcher that:
- Opens with its own dedicated shortcut after onboarding is complete
- Starts recording immediately with an animated listening indicator instead of a text field
- Keeps the panel visible until you click Cancel or press the voice shortcut again
- Finishes transcription and sends the spoken prompt to the selected agent when you trigger the shortcut again
The main app window can also be surfaced directly with its own shortcut:
- Defaults to
Ctrl+Option+K - Shows the main Kotoba Libre window after onboarding without opening the launcher
- Hides the main window again when you trigger it a second time
Kotoba Libre currently supports:
kotobalibre://open?url=<encoded_url>kotobalibre://preset/<presetId>?query=<encoded_query>kotobalibre://settings- Other
kotobalibre://...routes are treated as instance-relative paths and loaded against the configured LibreChat base URL kotobalibre://<instance-host>/oauth/openid/callback?<query>https://.../app/open?url=<encoded_url>https://.../app/preset/<presetId>?query=<encoded_query>https://.../app/settings
Top-level WKWebView navigations send X-Kotoba-Libre: Kotoba Libre/<version> so LibreChat can recognize the desktop wrapper build that is making the request.
If another app opens a plain https://... URL with Kotoba Libre, the app accepts it as an in-app navigation when the URL host matches the configured LibreChat instance host. https://.../app/... paths still stay reserved for the explicit deep-link actions above.
The Instance Settings option that opens external login flows in the default browser depends on the browser extension redirecting the completed auth flow back to kotobalibre://....
See docs/architecture.md for behavior details.
Load the unpacked Chrome extension from scripts/chrome-extension/kotobalibre-openid-callback or the Firefox extension from scripts/firefox-extension/kotobalibre-openid-callback.
Both extensions:
- Uses browser-native redirect handling so callback navigations can be caught before the page renders
- Keeps the content-script redirect as a fallback for already-loaded callback pages
- Uses the same icon artwork as Kotoba Libre
- Opens its settings page when you click the extension icon
- Stores the allowed hosts and callback path with browser sync storage
- Defaults the callback path to
/oauth/openid/callback, so most setups only need a host entry - Preserves an optional
:portin callback hosts, solocalhost:3000-style setups redirect correctly - Accepts plain hosts, HTTPS base URLs, or pasted callback URLs in its settings and normalizes them into a working redirect rule
- Always redirects into the fixed
kotobalibre://scheme - Starts inactive on a fresh install and opens its settings page so each user can enter their own default config
The Firefox build uses webRequest blocking redirects instead of Chrome dynamic rules, but it keeps the same settings model and redirect behavior.
To test it in Chrome:
- Open
chrome://extensions - Enable Developer mode
- Click
Load unpacked - Select
scripts/chrome-extension/kotobalibre-openid-callback - When the extension opens its setup page, enter the host list and callback path you want to use
- Retry the login flow
To test it in Firefox:
- Open
about:debugging#/runtime/this-firefox - Click
Load Temporary Add-on - Select
scripts/firefox-extension/kotobalibre-openid-callback/manifest.json - When the extension opens its setup page, enter the host list and callback path you want to use
- Retry the login flow
To create distributable source zips for the extensions:
./scripts/package-chrome-extension.sh
./scripts/package-firefox-extension.shThat writes dist-artifacts/chrome-extension/kotobalibre-openid-callback.zip and dist-artifacts/firefox-extension/kotobalibre-openid-callback.zip with the extension files at the archive root, which is the shape you want for sharing or browser-store upload.
The release workflow also builds and publishes both extension zips alongside the unsigned app artifacts.
App data is stored under the user Application Support directory in:
settings.jsonpresets.json
The files are managed through AppDataStore and recreated automatically when needed.
The canonical version lives in VERSION.
Validate the version before release:
./scripts/ci/validate-version.sh v0.1.0Unsigned release automation is defined in .github/workflows/release.yml.
The release workflow is launched manually from the default branch, creates the release tag for the selected patch, minor, or major bump, publishes the unsigned DMG plus both browser extension zips to GitHub Releases, and then advances VERSION to the next -dev version on the default branch.
The launcher glow effect in Sources/KotobaLibreApp/Views.swift is adapted from the MIT-licensed IntelligenceGlow reference implementation. Kotoba Libre does not include that package as a dependency.
See THIRD_PARTY_NOTICES.md for the full attribution and license notice.
Kotoba Libre is licensed under the GNU General Public License v2.0. See LICENSE.
More detail: