Zhongshu Audit ce39ab8be1 docs: App Store screenshots placeholders + APPSTORE_METADATA.md
App Store Connect requires screenshots at 1290x2796 (6.7") and
1179x2556 (6.1") for the iPhone 17 Pro Max / 17 / Pro lineup,
with at least 3 and at most 10 images per size. The repository
previously had no screenshots in docs/.

This commit adds:
  - scripts/generate_screenshot_placeholders.py - PIL-based
    generator that produces 5x 6.7" + 5x 6.1" placeholders with
    status bar, mock device frame, keyboard mock, and headline /
    subtitle text.
  - docs/screenshots/6.7/ and 6.1/ with 5 placeholder PNGs each
    (10 total, all at the correct Apple-mandated dimensions).
  - docs/screenshots/README.md explaining the dimensions,
    generation script, and how to capture real Simulator
    screenshots via `xcrun simctl io booted screenshot`.
  - docs/APPSTORE_METADATA.md - a single source of truth for
    every field in App Store Connect: name, subtitle, URLs,
    pricing, description (<=4000 chars), promotional text
    (<=170 chars), keywords (<=100 chars), release notes
    (<=4000 chars), what's new, App Privacy answers
    (Data Not Collected), encryption declaration, and reviewer
    notes.
  - AUDIT_APPSTORE.md - the v0.1.2 pre-launch audit report
    with 6 P0 items, 5 P1 items, 4 P2 items, and a 9-item
    "cross-cutting observations" section addressing the items
    in the original brief that turned out to be non-issues
    (CFBundleURLTypes in keyboard ext, NSSupportsLiveText,
    AppGroup fatalError inconsistency, AudioCaptureService
    interaction with AVAudioSession, ASRService SFSpeechRecognizer
    references). Includes an Appendix A with the local
    xcodebuild build + test results.

Important: the placeholder PNGs are intentionally bland - they
exist so App Store Connect accepts the dimensions. They MUST
be replaced with real Simulator screenshots before the actual
upload, see docs/screenshots/README.md for the workflow.

Refs: AUDIT_APPSTORE.md P0-5
2026-06-20 21:34:04 +08:00
2026-06-17 23:08:58 +08:00
2026-06-17 23:08:58 +08:00

OSGKeyboard

Hold a key, speak, release — AI-polished text appears at your cursor in any app. An open-source, custom-keyboard-based voice input tool for iOS 26+, inspired by Typeless and OpenLess.

Platform Swift License CI

中文 README


What is it?

OSGKeyboard is a free, open alternative to commercial voice-input tools. It runs as a Custom Keyboard Extension on iOS, so you can use it in any app — Messages, Notes, Mail, ChatGPT, Claude, Cursor, you name it.

  1. Press and hold the mic key
  2. Speak naturally
  3. Release — the AI polishes your words into clean text and inserts it at the cursor

The audio stays on-device (transcribed by Apple's on-device SpeechAnalyzer + DictationTranscriber on iOS 26+). Only the polished transcript is sent to your chosen cloud LLM. No audio ever leaves your phone.


Features

  • 🎙 Push-to-talk with a Typeless-style circular mic button
  • 🧠 On-device ASR (SpeechAnalyzer + DictationTranscriber, iOS 26+)
  • ✍️ AI polishing — adds structure, punctuation, fixes grammar, optionally produces lists
  • 🔌 Bring-your-own API — works with any OpenAI-compatible endpoint (OpenAI, DeepSeek, Qwen DashScope, your own self-hosted server, …)
  • 🔒 Privacy first — audio never leaves your device; transcripts only sent to the LLM you choose
  • 🎨 Native SwiftUI — dark theme, frosted glass, ~2000 lines of Swift
  • 🪶 Zero dependencies — no SwiftPM packages, no CocoaPods, no Carthage

Quick start

Requirements

Build & run

git clone https://github.com/hkgood/OSGKeyboard.git
cd OSGKeyboard
xcodegen generate          # produces OSGKeyboard.xcodeproj
open OSGKeyboard.xcodeproj # or build via CLI:
xcodebuild -project OSGKeyboard.xcodeproj -scheme OSGKeyboard \
  -destination 'generic/platform=iOS Simulator' build

Enable the keyboard in iOS

  1. Run the app on your device or simulator.
  2. Follow the 3-step onboarding: enable the keyboard in iOS Settings, then allow Full Access (required for the mic and LLM calls), then paste your API key.
  3. In any text field, tap 🌐 to switch to OSGKeyboard.
  4. Press and hold the mic, speak, release. ✨

"Allow Full Access" is required. Without it, iOS blocks the keyboard from using the microphone and from making network requests. We never log, store, or transmit your keystrokes — see PrivacyInfo.xcprivacy.


Architecture

OSGKeyboard/
├── OSGKeyboard/                 # Main iOS app (settings, onboarding)
│   ├── Views/                   # SwiftUI screens
│   ├── OSGKeyboardApp.swift     # @main entry
│   ├── PrivacyInfo.xcprivacy    # Required privacy manifest
│   └── OSGKeyboard.entitlements # App Group declaration
├── OSGKeyboardExt/              # Custom Keyboard Extension
│   ├── KeyboardViewController.swift   # Principal class
│   ├── Services/
│   │   ├── AudioCaptureService.swift  # AVAudioEngine → 16 kHz PCM
│   │   ├── ASRService.swift           # iOS 26 SpeechAnalyzer ASR
│   │   └── PolishingService.swift     # LLM call with timeout
│   └── Views/                   # RecordButton, Waveform, KeyboardRootView
├── OSGKeyboardShared/           # Framework shared by app + extension
│   ├── Models/                  # ProviderConfig, LLMRequest, LLMProvider
│   ├── Services/                # LLMClient (OpenAI-compatible)
│   └── Constants/               # AppGroup identifier
├── OSGKeyboardTests/            # XCTest unit tests
├── project.yml                  # XcodeGen project definition
└── .github/workflows/ci.yml     # Lint + build CI

Data flow

[Long-press mic] → AudioCaptureService → AudioBufferSnapshot (16 kHz mono)
                                          ↓
                                  ASRService.transcribe()
                                          ↓
                                ASREvent.final(rawTranscript)
                                          ↓
                              PolishingService.polish()
                                          ↓
                            LLMClient (OpenAI-compatible)
                                          ↓
                          textDocumentProxy.insertText(polished)

Adding a new LLM provider

Open OSGKeyboardShared/Models/LLMProvider.swift and append a new LLMProvider to the presets array. The default OpenAICompatibleClient handles any endpoint that speaks the POST /chat/completions protocol.

LLMProvider(
    id: "groq",
    name: "Groq",
    defaultBaseURL: "https://api.groq.com/openai/v1",
    defaultModel: "llama-3.1-70b-versatile",
    apiKeyURL: URL(string: "https://console.groq.com/keys")
)

That's it. No other code changes required.


Limitations

  • iOS sandboxes keyboard extensions: ~60 MB memory cap, Full Access required.
  • The keyboard does not work in password fields or some WKWebView textareas (iOS limitation).
  • iOS 26+ only. Earlier iOS versions are not supported.

License

MIT — use it, fork it, ship it. No warranty.


Acknowledgements


Note: the project is published at hkgood/OSGKeyboard; badges and git clone URLs already point there.

S
Description
No description provided
Readme
87 MiB
Languages
Swift 84.9%
Python 13.1%
HTML 0.8%
Shell 0.7%
Objective-C++ 0.3%
Other 0.1%