# Show HN: Sidekick – The zot coding agent, one click away on macOS

> Source: <https://github.com/patriceckhart/zot-sidekick>
> Published: 2026-06-06 07:23:49+00:00

A macOS menu bar app that provides quick access to zot from anywhere on your system.

**Let zot sidekick whip up your emails:**

**Let zot sidekick give your code a glow-up:**

**Menu Bar Integration**: Lives in your menu bar for quick access** Global Hotkey**: Long-press the Right Option key to toggle the panel from anywhere** Floating Panel**: Spotlight-style centered floating window that remembers its position and size** Chat Interface**: Clean, dark-themed chat interface with streaming responses** Image Support**: Drag and drop images for vision-based queries** Sessions**: Conversations auto-save and can be browsed, searched, reloaded, and deleted** Working Directory**: Set context for file operations** Inline Settings**: Configure provider, authentication (API key or subscription), and model directly in the panel

- macOS 26 or later
- A recent Xcode (the project targets the macOS 26 SDK)
- An Anthropic, OpenAI, etc. API key, or a supported subscription login

Note on subscription login.The OAuth client IDs used are the ones published in Anthropic's Claude Code CLI, OpenAI's Codex CLI, and the Kimi Code CLI device-code flow. Reusing them from a third-party tool may be against their terms of service and may be revoked at any time. Use it at your own risk; the API-key flow is the safe default.

The `zot`

binary is **baked into the app bundle**, downloaded from the
[official GitHub releases](https://github.com/patriceckhart/zot). No separate
zot install is required, and the app never uses any zot on your system PATH.

On launch the app checks the
[zot-sidekick releases](https://github.com/patriceckhart/zot-sidekick/releases)
and compares the latest tag with its own version (`AppUpdater.swift`

). When a
newer release exists, a small primary "Update" button appears in the panel top
bar (after Settings and Sessions) that opens the latest release page.

The app manages its own copy of the zot binary in Application Support and
updates it entirely in Swift (`ZotUpdater.swift`

):

- On launch and on demand it checks the GitHub releases API for the latest version.
- When a newer version exists, Settings shows a primary "Update zot" button that downloads the correct darwin build for your architecture, extracts it, and atomically replaces the installed binary, then restarts the bridge.
- The bundled in-app copy only seeds the first install; downloaded updates are preferred and are not overwritten unless a newer build ships in the app.

No shell script is involved at runtime.

`scripts/bundle-zot.sh`

is a pre-release helper to refresh the binary that
ships inside the app bundle. It is not part of the running app and does not
affect the in-app update path.

- Open
`zot sidekick.xcodeproj`

in Xcode - Build and run (Cmd+R)
- Grant Accessibility (for the global hotkey and "Paste into") via the menu bar icon's right-click menu ("Open Accessibility Settings"); Screen Recording is requested lazily the first time you take a screenshot
- Open the panel and click the gear (Settings) in the top bar to configure authentication

**Menu Bar Click**: Click the icon in the menu bar to toggle the panel** Global Hotkey**: Long-press the Right Option key (about 0.4s) to toggle it from anywhere** Dismiss**: Press Escape or click the menu bar icon again

The panel remembers the position and size you drag it to across hide/show. It resets to the default centered position only when you quit and relaunch.

- Type your question in the input field at the bottom
- Press Enter or click the send button
- Drag and drop images onto the window to include them in your query
- Click "Copy" on any assistant response to copy it to clipboard
- Click "Paste into …" to paste the response into your previously active application

- Click the folder icon in the input bar to set a working directory
- zot will use this directory as context for file operations

- Conversations are saved automatically after each reply
- Click "Sessions" in the panel top bar to browse, search, reload, or delete saved sessions
- Sessions are stored as flat JSON files in
`~/Library/Application Support/zot sidekick/sessions/`

(no project folders) - Click "+ New" to start a fresh conversation

- Click the gear (Settings) in the panel top bar to open settings inline
- Configure:
- Provider (Anthropic, OpenAI, ChatGPT Subscription, Kimi, Google, DeepSeek, Ollama)
- Authentication: either a subscription login or an API key
- Default Model
- zot binary version, with a primary "Check for Updates" / "Update zot" button

Providers that support subscriptions (Anthropic Claude, ChatGPT, Kimi) offer a "Log in with subscription" button. This runs the same OAuth flow as the zot CLI:

- Anthropic and ChatGPT open a browser and capture the callback on a local loopback port (PKCE).
- Kimi uses the OAuth device flow (a code plus a browser page).

Tokens are written to the bundled binary's `ZOT_HOME/auth.json`

, so the
embedded zot uses your subscription with no extra setup. API keys are stored
the same way. Use "Sign Out" to remove stored credentials for a provider.

The model picker shows models from every provider you are logged into, grouped
by provider. The full live model list per provider is fetched via a one-shot
`zot rpc`

query (`ZotModelFetcher`

). Choosing a model from a different provider
switches the active provider and restarts the bridge with its credentials.

**AppDelegate**: Owns the menu bar icon, the panel, and the global hotkey** HotkeyMonitor**: Long-press Right Option detection (CGEvent tap with an NSEvent fallback)** PanelController**: Controls the floating panel window and remembers its frame** PanelChatView**: SwiftUI chat UI, including the inline settings overlay (`InlineSettingsView`

) and the typing indicator**AppState**: Observable state management with`@Observable`

, plus binary preparation and session/auth orchestration**ZotBridge**: Spawns and communicates with the bundled`zot rpc`

process via JSON-RPC**SessionStore**: Flat-file JSON persistence for sessions (no project folders)** ZotAuth / ZotOAuthLogin**: API keys and subscription OAuth, written to`ZOT_HOME/auth.json`

**ZotUpdater**: GitHub release checks and in-Swift download/install of the bundled zot binary** AppUpdater**: Checks zot-sidekick releases and surfaces the in-app "Update" button** ZotModelFetcher**: One-shot RPC that fetches the full live model list per authenticated provider** SettingsWindow**: A standalone settings window (legacy fallback; the inline panel settings are the primary path)

The app uses:

- SwiftUI for the UI
- Observation framework for state management
- ScreenCaptureKit for screenshot functionality
- Process for spawning the bundled zot binary
- NWListener loopback servers for OAuth callbacks
- Icon Composer (
`Icon.icon`

) for the Liquid Glass app icon, with a classic`AppIcon.appiconset`

as the fallback for older macOS

The app icon is an Icon Composer bundle (`Icon.icon`

). Because the CI runner's
`actool`

can crash compiling `.icon`

, the catalog is precompiled on a Mac with
a recent Xcode into `prebuilt-icon/Assets.car`

(plus `Icon.icns`

) via
`scripts/compile-icon.sh`

, committed, and injected into the built app by the
workflow. Re-run that script and commit `prebuilt-icon/`

whenever the icon or
asset catalog changes. The classic `AppIcon.appiconset`

remains as a fallback
for pre-26 macOS.

`.github/workflows/build-dmg.yml`

builds the app on `macos-latest`

(pinned to
the latest Xcode) on every push and on manual dispatch. It:

- auto-versions each build from the run number with rollover
(
`0.0.1 ... 0.0.99 -> 0.1.0 ... 0.99.99 -> 1.0.0 ...`

), - signs the app (including the embedded zot binary) with a Developer ID certificate and hardened runtime, then notarizes and staples the DMG,
- packages a
`zot-sidekick-<version>.dmg`

containing the app and an`Applications`

symlink for drag-and-drop install, - uploads the DMG as a build artifact, and publishes a GitHub Release
(tag
`vX.Y.Z`

, marked as latest) on every push to`main`

.

Releases are notarized Developer ID builds, so they launch without Gatekeeper warnings. If the signing secrets are absent, the workflow falls back to an ad-hoc signature; such builds require a right-click "Open" on first launch and re-prompt for Accessibility on every launch.

This app bundles the zot binary and spawns it as a child process that reads
and writes files anywhere and runs developer tools. That model requires the
sandbox to be off (`ENABLE_APP_SANDBOX = NO`

) and is therefore distributed as
a notarized, Developer ID-signed build outside the Mac App Store, the same as
the zot CLI itself. The Mac App Store requires a sandbox that would prevent
the embedded agent from doing its job, so it is not a target for this app.

For release: archive in Xcode, sign with your Developer ID (deep-signing the
embedded `zot-bin`

), notarize with `notarytool`

, then staple and ship the
`.dmg`

.

MIT
