Skip to content

Repository files navigation

Overtype

Overtype is a native, lightweight macOS menu bar utility that applies AI-powered transformations (like grammar correction) directly to text you select in any application.

It securely modifies text via macOS Accessibility APIs, completely bypassing the system clipboard to ensure maximum privacy and compliance with enterprise security policies.

Features

  • Clipboard Isolation: Overtype never touches NSPasteboard. It reads and types text strictly through the macOS Accessibility API (AXUIElement & CGEvent).
  • AI Integrations: Natively supports OpenAI (like GPT-5.4-nano), Google Gemini, Anthropic Claude, and Ollama for models running locally on your own Mac.
  • Global Hotkeys: Highlight text in any application (like MS Teams or Apple Notes), hit a shortcut (e.g. ⌃⌥⌘G), and watch the text get magically replaced inline.
  • Privacy First: By default, sensitive text is never written to disk; only standard, sanitized application logs are recorded. Unredacted text is logged only if you explicitly enable debug logging.

Installation

Via Homebrew (Recommended)

You can easily install Overtype using our custom Homebrew tap:

brew install stn1slv/tap/overtype

Homebrew prints these notes after installing and after every upgrade; they are repeated here because both are easy to hit.

First launch may be blocked. Overtype is ad-hoc signed and not notarized, so Gatekeeper can refuse to open it. Remove the quarantine attribute and try again:

xattr -dr com.apple.quarantine "/Applications/Overtype.app"

Accessibility permission must be re-granted after every upgrade. macOS ties the permission to the app's code signature, and an ad-hoc signature changes with every build, so an upgraded copy is a different app as far as the system is concerned. The catch is that the old entry stays in the list and stays enabled, so nothing looks wrong while Overtype silently fails to read your selection. In System Settings > Privacy & Security > Accessibility, select Overtype, remove it with the - button, then add the upgraded app and enable it.

Both go away if the app is ever signed with an Apple Developer ID certificate and notarized.

Manual Installation

  1. Build the Application:
    ./scripts/build-app.sh
  2. Launch: Open the generated bundle Overtype.app inside the root directory or move it to /Applications.

Setup

  1. Accessibility Permissions: On first launch, macOS will prompt you to grant Accessibility permissions in System Settings > Privacy & Security > Accessibility. This is required for Overtype to read the focused text field.
  2. API Key Setup: Click the Overtype menu bar icon (the quotation mark), open Settings, and paste your OpenAI API key. This key is stored securely in your macOS Keychain and is never written to plaintext config files. For detailed step-by-step instructions, see our OpenAI Setup Guide.

Configuration Settings

You can manage all your preferences, providers, actions, and global hotkeys directly from the in-app Settings window (available via the menu bar icon). Any changes made in the GUI are automatically validated and written back to the configuration file stored at ~/Library/Application Support/Overtype/config.json. Advanced users can still view or migrate this file manually.

{
  "global": {
    "typingSpeedMultiplier": 1.0,
    "showHUD": true,
    "typingChunkSize": 20,
    "typingDelayMicroseconds": 2000,
    "appTypingOverrides": {
      "com.microsoft.Outlook": { "typingChunkSize": 1, "typingDelayMicroseconds": 10000 }
    }
  },
  "providers": [
    {
      "id": "openai",
      "kind": "openai",
      "baseURL": "https://api.openai.com/v1",
      "defaultModel": "gpt-5.4-nano",
      "timeoutSeconds": 30.0,
      "retryDelaySeconds": 0.5,
      "keychainKey": "overtype-openai-key"
    }
  ],
  "actions": [
    {
      "id": "fix-grammar",
      "title": "Fix grammar",
      "enabled": true,
      "shortcut": { "keyCode": 5, "modifiers": 1835008, "displayString": "⌃⌥⌘G" },
      "providerID": "openai",
      "model": null,
      "systemPrompt": "You are a proofreader. Fix grammar, spelling, and punctuation...",
      "userPromptTemplate": "{{text}}",
      "temperature": 0.0,
      "maxInputCharacters": 5000,
      "allowNewlines": false,
      "writeStrategy": "typing"
    }
  ]
}

Configuring Typing Speed & Performance

Overtype sends simulated keystrokes to type out the AI's response inline. You can tune the typing performance inside the "global" configuration block:

  • typingChunkSize (Integer, default 20): The number of UTF-16 characters sent in a single keystroke event. Chunking makes text insertion dramatically faster.
  • typingDelayMicroseconds (Integer, default 2000): The delay in microseconds between sending chunks (the default 2000 is 2 ms). If certain apps drop characters, try increasing this delay.
  • typingSpeedMultiplier (Double, default 1.0): Scales the effective delay between chunks. Values above 1.0 type faster (shorter delay); values below 1.0 type slower.
  • appTypingOverrides (Object, optional): Per-application typing overrides keyed by macOS bundle identifier. Each entry may set typingChunkSize and/or typingDelayMicroseconds; any field left out falls back to the global value. Use this for web/Chromium-based editors (such as the new Outlook) that apply synthetic keystrokes asynchronously and corrupt the output at the default fast cadence. The default configuration ships a verified profile for the new Outlook (com.microsoft.Outlook) that types one character at a time with a 10 ms delay.

Configuring the API Key

Because Overtype values privacy and security, API keys are never stored in your config.json file. Instead:

  1. The provider config defines a "keychainKey" (e.g. "overtype-openai-key").
  2. When you paste your API key into the Overtype Settings window, it saves it securely into the macOS Keychain under that exact name.
  3. At runtime, the Action Engine dynamically retrieves the key from the Keychain.

Specifying the AI Model

Overtype resolves the AI model to use in the following order:

  1. Action-level model: If an action specifies a "model" key (e.g. "model": "gpt-4o-mini"), it is used. This allows you to use faster/cheaper models for simple tasks and heavier models for complex rewrites.
  2. Provider-level default: If the action omits the model, Overtype falls back to the "defaultModel" specified in the provider's configuration.

Using Google Gemini

Overtype talks to Google Gemini natively (it calls the Gemini generateContent API directly; your text is never sent to any intermediary). Enabling it is pure configuration, no rebuild required.

  1. Get a Gemini API key from Google AI Studio.

  2. Add a Gemini provider block to the "providers" array in ~/Library/Application Support/Overtype/config.json:

    {
      "id": "gemini",
      "kind": "gemini",
      "defaultModel": "gemini-3.5-flash-lite",
      "timeoutSeconds": 30.0,
      "retryDelaySeconds": 0.5,
      "keychainKey": "overtype-gemini-key"
    }

    The "baseURL" may be omitted; Overtype defaults to https://generativelanguage.googleapis.com/v1beta/.

  3. Store your key in the macOS Keychain under the exact keychainKey name. Adding the provider through Settings → Providers does this for you; the Terminal command below is the manual equivalent if you are editing config.json by hand:

    security add-generic-password -a "overtype-gemini-key" -w "YOUR_GEMINI_API_KEY" -U

    The -a (account) value must match keychainKey exactly — Overtype looks the item up by account, not by service.

  4. Point an action at the provider by setting its "providerID" to "gemini" (optionally set a per-action "model" to override the default). The key is sent in the x-goog-api-key request header and never written to config.json, logs, or the URL.

The shipped default configuration does not include a Gemini provider, so a fresh install adds no extra provider or shortcut until you add the block above.

Using Anthropic Claude

Overtype talks to Anthropic natively (it calls the Messages API directly; your text is never sent to any intermediary). You can add it from Settings → Providers, where "Anthropic" now appears in the Kind picker, or by editing configuration directly. Either way, no rebuild is required.

  1. Get an API key from the Anthropic Console.

  2. Add an Anthropic provider block to the "providers" array in ~/Library/Application Support/Overtype/config.json:

    {
      "id": "anthropic",
      "kind": "anthropic",
      "defaultModel": "claude-haiku-4-5",
      "timeoutSeconds": 30.0,
      "retryDelaySeconds": 0.5,
      "keychainKey": "overtype-anthropic-key"
    }

    The "baseURL" may be omitted; Overtype defaults to https://api.anthropic.com/v1/.

    claude-haiku-4-5 is recommended as the default because Overtype rewrites a selection inline while you wait, so speed matters more than raw capability here. Any Claude model works — set a heavier one per action if you want.

  3. Store your key in the macOS Keychain under the exact keychainKey name. Adding the provider through Settings → Providers does this for you; the Terminal command below is the manual equivalent if you are editing config.json by hand:

    security add-generic-password -a "overtype-anthropic-key" -w "YOUR_ANTHROPIC_API_KEY" -U

    The -a (account) value must match keychainKey exactly — Overtype looks the item up by account, not by service.

    Approve the Keychain prompt before your first real run. An item created this way trusts no application, so the first time Overtype reads it macOS shows an authorization dialog. That dialog takes keyboard focus, which destroys your text selection and aborts the run. Trigger the action once on throwaway text, choose Always Allow, and subsequent runs are silent. Keys added through Settings → Providers are written by Overtype itself and never show this prompt.

  4. Point an action at the provider by setting its "providerID" to "anthropic" (optionally set a per-action "model" to override the default). The key is sent in the x-api-key request header and never written to config.json, logs, or the URL.

Note: an action's "temperature" is ignored for Anthropic runs. Newer Claude models (the Opus 4.7/4.8, Opus 5, Sonnet 5 and Fable 5 generation) reject that parameter with an HTTP 400. Older ones such as claude-haiku-4-5 still accept it, but Overtype never sends it to Anthropic rather than maintaining a per-model list that would go stale on every release. The setting still applies to OpenAI and Gemini providers.

The shipped default configuration does not include an Anthropic provider, so a fresh install adds no extra provider or shortcut until you add the block above.

Using Ollama (local models)

Overtype talks to a local Ollama service natively (it calls /api/chat directly). This is the one provider where your text never leaves your Mac: with the default configuration the only address contacted is localhost, so a run is designed to work with the machine fully offline. You can add it from Settings → Providers, where "Ollama" appears in the Kind picker, or by editing configuration directly. Either way, no rebuild is required.

  1. Install Ollama and download a model yourself. Overtype never downloads, installs, starts, or stops anything on your behalf:

    brew install ollama     # or download from ollama.com
    ollama serve            # start the service
    ollama pull llama3.2    # about 2 GB
  2. Add an Ollama provider block to the "providers" array in ~/Library/Application Support/Overtype/config.json:

    {
      "id": "ollama-local",
      "kind": "ollama",
      "defaultModel": "llama3.2",
      "timeoutSeconds": 30.0,
      "retryDelaySeconds": 0.5
    }

    The "baseURL" may be omitted; Overtype defaults to http://localhost:11434. Set it if your service listens on another port, or runs on another machine on your network.

    Plain http:// works for localhost, a .local name, and private LAN addresses (192.168.x.x, 10.x.x.x) — macOS App Transport Security exempts local networking, verified from the built app. A service on a public address must use https://; plain HTTP to a public host is blocked by macOS and the run will fail with a network error.

    llama3.2 is recommended as the default because Overtype rewrites a selection inline while you wait, so a small fast model is the difference between a usable and an unusable experience on a laptop. Any model you have installed works — set a heavier one per action if you want.

  3. No API key is needed. There is no "keychainKey" in the block above, and the API Key field in Settings is marked optional for this provider — leave it empty. Enter a key only if you point the provider at a remote or password-protected Ollama deployment; it is then stored in the Keychain and sent as an Authorization: Bearer header (the same scheme the OpenAI-compatible provider uses; Gemini and Anthropic use their own headers). Switching an existing provider's Kind to Ollama discards any key stored for it, so a cloud key is never re-sent to a local endpoint.

  4. Point an action at the provider by setting its "providerID" to "ollama-local" (optionally set a per-action "model" to override the default).

Size limit. Ollama is the only provider with its own input limit. A request is refused before anything is sent if its prompt is too large for the model, with an error saying so. Three things determine that limit:

  • It is measured in UTF-8 bytes, roughly 6,000. For English that is about 6,000 characters; for Chinese, Japanese or Korean it is closer to 2,000, and emoji cost more still. That is not pessimism — measured against a real model, 100 CJK characters cost 328 tokens, about one per byte.
  • The action's system prompt counts too, not just your selection. The shipped prompt (~170 characters) leaves a full 5,000-character selection comfortable, but an action carrying a long style guide or few-shot examples leaves correspondingly less room.
  • A model with a small context window gets a smaller limit. Overtype asks the service what window your model actually has and uses half of it, since the other half is where the rewrite is generated. A 2,048-token model therefore allows about 1,024 tokens of prompt, not 6,000.

The limit exists because the model's context window has to hold your selection and its rewrite. Without it the service quietly drops part of your text — measured, not theorised — and Overtype would replace your whole selection with a rewrite of a fragment.

The first run after a pause is slower. Ollama unloads an idle model after a few minutes and reloads it on the next request, which can take several seconds on its own. Overtype deliberately does not ask the service to keep your model resident — that would silently hold gigabytes of memory between runs. If you want it kept loaded, use Ollama's own OLLAMA_KEEP_ALIVE setting.

With "timeoutSeconds": 30.0 a first run on slower hardware, or with a large model, can hit the time limit and report a timeout. That is expected; run it again once the model is loaded, or raise the provider's time limit (the Settings slider goes up to 300 seconds).

Note: unlike Anthropic, an action's "temperature" is sent to Ollama. The service applies it itself as a generation option, so every model accepts it.

The shipped default configuration does not include an Ollama provider, so a fresh install adds no extra provider or shortcut until you add the block above.

Security & Privacy Constraints

  • No Clipboard: The system pasteboard (NSPasteboard) is strictly avoided to prevent triggering clipboard monitoring tools or leaking secrets.
  • Destructive Isolation: Overtype only edits text that is actively selected. It will not blindly delete and retype text if the user loses focus.
  • Keychain Storage: API keys are stored securely using macOS Keychain (kSecClassGenericPassword), never in plaintext JSON.

License

MIT License.

About

A native macOS menu bar utility that applies AI-powered text transformations (like grammar correction) inline anywhere you type, completely bypassing the clipboard for maximum privacy.

Topics

Resources

Stars

4 stars

Watchers

0 watching

Forks

Releases

Used by

Contributors

Languages