Use your Claude Pro/Max subscription — not an API key — for on-device text post-processing in TypeWhisper on macOS.
TypeWhisper cleans up and rewrites your dictated text with an LLM. Out of the box that means a pay-per-token API key. This plugin lets the LLM step run on the Claude Pro/Max subscription you already pay for: it signs in through Anthropic's OAuth flow and calls the Claude Messages API with those tokens, so dictation post-processing costs nothing beyond your existing plan.
End-to-end verified: 53/53 tests pass, and the plugin loads, logs in via OAuth, and calls the Anthropic Messages API from inside TypeWhisper 1.4.0.
A native macOS plugin (Swift, built against the TypeWhisper Plugin SDK) that registers as an LLM provider inside TypeWhisper. Once connected it appears in the app's model picker like any other backend. Concretely it:
- Authenticates with Anthropic via OAuth + PKCE (S256) using the Pro/Max subscription, instead of an API key.
- Sends post-processing requests to the Claude Messages API, choosing Haiku, Sonnet, or Opus.
- Stores tokens in the macOS Keychain and keeps them refreshed automatically in the background.
- Makes no telemetry or analytics calls — the only hosts it ever contacts are Anthropic's
(
claude.ai,platform.claude.com,api.anthropic.com).
It is a single, self-contained .bundle. There is no server, no account beyond your Claude
subscription, and no third-party dependency outside the TypeWhisper SDK.
This is not an official Anthropic or TypeWhisper plugin. It uses the same OAuth client ID that Claude Code uses internally to authenticate against the Anthropic API, and identifies its API calls as Claude Code requests so the Pro/Max subscription accepts the inference. This sits in a gray area of Anthropic's Terms of Service. Use at your own risk — excessive use may result in account action.
Prerequisites: macOS 14+ (Apple Silicon), the Swift toolchain (Xcode or Command Line Tools),
TypeWhisper 1.4.0+ installed at /Applications/TypeWhisper.app, and an active Claude Pro/Max
subscription.
Build and install in one step:
./scripts/build-plugin.sh --installThen quit and restart TypeWhisper. The plugin appears under Settings → Plugins → Claude (OAuth Pro/Max).
./scripts/build-plugin.sh
# Bundle is at .build/release/ClaudeOAuthPlugin.bundleswift build -c release— produceslibClaudeOAuthPlugin.dylib.- Assembles
ClaudeOAuthPlugin.bundle(Contents/MacOS/ClaudeOAuthPlugin,Contents/Resources/manifest.json,Contents/Info.plist). - Patches the binary with
install_name_tool:- Changes the SDK reference from
@rpath/libTypeWhisperPluginSDK.dylib(the SPM build output) to@rpath/TypeWhisperPluginSDK.framework/Versions/A/TypeWhisperPluginSDK(what TypeWhisper.app ships). - Adds
/Applications/TypeWhisper.app/Contents/Frameworksas anLC_RPATHso the framework resolves at runtime.
- Changes the SDK reference from
- Ad-hoc code-signs the bundle (Gatekeeper accepts ad-hoc signatures on user-installed plugins).
- With
--install: copies the bundle to~/Library/Application Support/TypeWhisper/Plugins/.
~/Library/Application Support/TypeWhisper/Plugins/
Verified at TypeWhisper 1.4.0 (build 803). The directory sits alongside PluginData/ (where
plugins store their own state).
- Open Settings → Plugins → Claude (OAuth Pro/Max) inside TypeWhisper and activate it.
- Click "Mit Claude verbinden". Your default browser opens at
claude.ai/oauth/authorize. - Log in with your Claude Pro/Max account and confirm the permission grant.
platform.claude.comshows an authorization code in the form<code>#<state>. Copy the whole thing.- Paste it into the plugin's code field and click "Bestätigen".
- The plugin splits the input at
#, verifies thestatematches the login it started (a CSRF guard), exchanges the code for access + refresh tokens, and stores them in the macOS Keychain undercom.guttmann.typewhisper-claude.oauth.
Anthropic's refresh tokens are single-use: every refresh returns a new refresh token, and the old one dies immediately. The plugin keeps the chain rotated and warm by:
- Ticking every 60 seconds while TypeWhisper runs, refreshing whenever less than 15 minutes of validity remain.
- Refreshing on plugin activation, and before each
process()call if less than 5 minutes remain. - Persisting the new tokens before returning from the refresh, so a rotated token is never lost.
This keeps you signed in as long as TypeWhisper opens at least every few days. If a refresh ever fails (e.g. the token was revoked), the settings panel shows an "expired" state and prompts you to reconnect.
| Model | Identifier | When |
|---|---|---|
| Haiku 4.5 (default) | claude-haiku-4-5 |
Fast post-processing of short voice snippets |
| Sonnet 4.6 | claude-sonnet-4-6 |
More careful rewriting |
| Opus 4.7 | claude-opus-4-7 |
Rare — complex transformations |
Switch via the model picker in the plugin settings. Your choice is persisted in plugin-scoped
UserDefaults through the SDK's HostServices.
Each request sends max_tokens: 2048. Temperature is set to 0.3 for Haiku and Sonnet but
omitted for Opus 4.7, which rejects the temperature parameter (see Known Issues).
- Authorize:
https://claude.ai/oauth/authorize— PKCE S256, scopesorg:create_api_key user:profile user:inference. - Token exchange / refresh:
https://platform.claude.com/v1/oauth/token. - Redirect URI:
https://platform.claude.com/oauth/code/callback— Anthropic renders the code on this page; the user copies it back into the plugin. - Client ID:
9d1c250a-e61b-44d9-88ed-5944d1962f5e(identical to Claude Code's client ID). - Inference:
https://api.anthropic.com/v1/messages.
manifest.json is the TypeWhisper plugin manifest — the metadata TypeWhisper reads to discover
and load the plugin. The build script copies it into the bundle at Contents/Resources/manifest.json.
Its fields:
| Field | Value | Meaning |
|---|---|---|
id |
com.guttmann.typewhisper-claude-oauth |
Unique plugin identifier |
name |
Claude (OAuth Pro/Max) |
Display name shown in TypeWhisper |
version |
0.1.0 |
Plugin version |
minHostVersion |
1.4.0 |
Oldest TypeWhisper version that can load it |
sdkCompatibilityVersion |
v1 |
Plugin SDK ABI this build targets |
minOSVersion |
14.0 |
Minimum macOS version |
supportedArchitectures |
["arm64"] |
Apple Silicon only |
category |
llm |
Registers the plugin as an LLM provider |
principalClass |
ClaudeOAuthLLMPlugin |
The Swift class TypeWhisper instantiates as the entry point |
The principalClass matches the @objc(ClaudeOAuthLLMPlugin) class in the source and the
NSPrincipalClass written into the bundle's Info.plist, so the host can find and instantiate the
plugin at load time.
-
TypeWhisper 1.4.0 drops the Fine-tuning field on Custom Workflow templates. When a workflow uses Eigener Workflow / Custom Workflow, the Feinabstimmung input is silently ignored — the plugin only receives the Anweisung as
systemPrompt. This is a TypeWhisper bug, not a plugin bug. Tracked upstream: typewhisper-mac#608. Workaround: paste the fine-tuning text at the end of the instruction field, or switch the workflow's template to Cleaned Text / Summary / Email Reply etc. (all of which correctly includefineTuningin the generated prompt). -
Opus 4.7 rejects the
temperatureparameter. Anthropic deprecatedtemperaturefor the Opus 4.7 reasoning model. The plugin omitstemperaturewhen the selected model starts withclaude-opus-4-7; for Haiku 4.5 and Sonnet 4.6 it still sendstemperature: 0.3.
swift build # compile
swift test # run the test suite (53 tests across 5 suites)Tests use the Swift Testing framework (@Test
macros) and run fully offline — network calls are stubbed via a URLProtocol mock and an in-memory
HostServices, so no real Anthropic credentials or requests are involved.
Submitted to the official TypeWhisper plugin catalog via a fork-and-pull-request against the upstream catalog repository.
To report a vulnerability, see SECURITY.md.
GPL-3.0-only — see LICENSE.
- Token-refresh and retry logic is modeled on an internal reference implementation of single-use refresh-token rotation.
- OAuth + PKCE flow patterns are adapted from an internal reference implementation of Anthropic OAuth authentication.