Claude
Skills
Sign in
Back

typeno-voice-input

Included with Lifetime
$97 forever

```markdown

Image & Video

What this skill does

```markdown
---
name: typeno-voice-input
description: TypeNo is a free, open source, privacy-first macOS menu bar app that captures voice via a Control key shortcut, transcribes locally using the coli speech engine, and pastes text into the active app.
triggers:
  - set up TypeNo voice input on macOS
  - add voice dictation to my Mac app
  - integrate TypeNo speech to text
  - build TypeNo from source
  - configure local voice transcription macOS
  - use TypeNo to paste voice input
  - fix TypeNo microphone or accessibility permissions
  - drag audio file to transcribe with TypeNo
---

# TypeNo Voice Input macOS Skill

> Skill by [ara.so](https://ara.so) — Daily 2026 Skills collection.

TypeNo is a minimal, privacy-first macOS menu bar app that records your voice on a Control key short-press, transcribes it locally via the [coli](https://github.com/marswaveai/coli) Node.js engine, and pastes the resulting text directly into whatever app is focused — no cloud, no accounts, no UI windows.

---

## What TypeNo Does

- **Global hotkey:** Short-press `Control` (< 300 ms, no modifier) → start/stop recording
- **Local transcription:** All speech processing runs on-device via the `coli` CLI
- **Auto-paste:** Transcribed text is typed into the active app and copied to the clipboard
- **Drag-to-transcribe:** Drop `.m4a`, `.mp3`, `.wav`, or `.aac` onto the menu bar icon
- **No preferences UI:** Zero configuration by design

---

## Installation

### 1. Install the coli speech engine

TypeNo shells out to `coli` for transcription. Install it globally:

```bash
npm install -g @marswave/coli
```

Verify:

```bash
coli --version
```

If `coli` is missing at launch, TypeNo shows an in-app prompt with the install command.

### 2a. Download the pre-built app

```bash
# Download latest release zip from GitHub
# https://github.com/marswaveai/TypeNo/releases/latest
# Download TypeNo.app.zip, unzip, move to /Applications
open /Applications/TypeNo.app
```

If macOS quarantines the app (not yet notarized):

```bash
xattr -dr com.apple.quarantine "/Applications/TypeNo.app"
open /Applications/TypeNo.app
```

Or right-click → **Open** in Finder, then **Open Anyway** in System Settings → Privacy & Security.

### 2b. Build from source

```bash
git clone https://github.com/marswaveai/TypeNo.git
cd TypeNo
scripts/generate_icon.sh   # generates app icon assets
scripts/build_app.sh       # compiles and bundles to dist/TypeNo.app
cp -R dist/TypeNo.app /Applications/
open /Applications/TypeNo.app
```

### 3. Grant one-time permissions

On first launch TypeNo requests:
- **Microphone** — for audio capture
- **Accessibility** — to simulate paste (⌘V) into the active app

Grant both in **System Settings → Privacy & Security**.

---

## Usage

| Action | How |
|---|---|
| Start recording | Short-press `Control` (< 300 ms, no other keys held) |
| Stop recording & transcribe | Short-press `Control` again |
| Start/stop via menu | Menu bar icon → **Record** |
| Transcribe an audio file | Drag `.m4a` / `.mp3` / `.wav` / `.aac` onto the menu bar icon |
| Check for updates | Menu bar icon → **Check for Updates...** |
| Quit | Menu bar icon → **Quit** (`⌘Q`) |

After stopping, TypeNo:
1. Sends audio to `coli` for local transcription
2. Pastes result into the previously focused app
3. Copies result to the clipboard

---

## Project Structure (Swift source)

```
TypeNo/
├── AppDelegate.swift          # NSApplicationDelegate, menu bar setup
├── AudioRecorder.swift        # AVFoundation capture logic
├── TranscriptionService.swift # Shells out to `coli` CLI
├── PasteService.swift         # Accessibility / CGEvent paste
├── HotkeyMonitor.swift        # Global CGEventTap for Control key
├── StatusBarController.swift  # NSStatusItem, menu construction
├── DragDropHandler.swift      # Drag audio files onto status icon
└── assets/
    └── hero.webp
scripts/
├── generate_icon.sh
└── build_app.sh
```

---

## Key Swift Patterns

### Global Control-key hotkey (CGEventTap)

```swift
// HotkeyMonitor.swift
import Cocoa

class HotkeyMonitor {
    private var eventTap: CFMachPort?
    private var pressStart: Date?
    private let maxPressDuration: TimeInterval = 0.3   // 300 ms

    func start(onToggle: @escaping () -> Void) {
        let mask: CGEventMask = (1 << CGEventType.flagsChanged.rawValue)
        eventTap = CGEvent.tapCreate(
            tap: .cgSessionEventTap,
            place: .headInsertEventTap,
            options: .defaultTap,
            eventsOfInterest: mask,
            callback: { proxy, type, event, refcon in
                let monitor = Unmanaged<HotkeyMonitor>
                    .fromOpaque(refcon!).takeUnretainedValue()
                monitor.handle(event: event)
                return Unmanaged.passUnretained(event)
            },
            userInfo: Unmanaged.passUnretained(self).toOpaque()
        )
        guard let tap = eventTap else { return }
        let loop = CFMachPortCreateRunLoopSource(nil, tap, 0)
        CFRunLoopAddSource(CFRunLoopGetCurrent(), loop, .commonModes)
        CGEvent.tapEnable(tap: tap, enable: true)
    }

    private func handle(event: CGEvent) {
        let flags = event.flags
        let onlyControl = flags.contains(.maskControl) &&
                          !flags.contains(.maskCommand) &&
                          !flags.contains(.maskAlternate) &&
                          !flags.contains(.maskShift)

        if onlyControl {
            pressStart = Date()
        } else if let start = pressStart {
            let duration = Date().timeIntervalSince(start)
            pressStart = nil
            if duration < maxPressDuration {
                DispatchQueue.main.async { self.onToggle?() }
            }
        }
    }

    var onToggle: (() -> Void)?
}
```

### Audio recording with AVFoundation

```swift
// AudioRecorder.swift
import AVFoundation

class AudioRecorder: NSObject {
    private var engine = AVAudioEngine()
    private var file: AVAudioFile?
    private(set) var outputURL: URL?

    func startRecording() throws {
        let dir = FileManager.default.temporaryDirectory
        let url = dir.appendingPathComponent(UUID().uuidString + ".wav")
        outputURL = url

        let input = engine.inputNode
        let format = input.outputFormat(forBus: 0)

        file = try AVAudioFile(forWriting: url,
                               settings: format.settings)

        input.installTap(onBus: 0, bufferSize: 4096, format: format) { [weak self] buffer, _ in
            try? self?.file?.write(from: buffer)
        }
        try engine.start()
    }

    func stopRecording() -> URL? {
        engine.inputNode.removeTap(onBus: 0)
        engine.stop()
        file = nil
        return outputURL
    }
}
```

### Transcription via coli CLI

```swift
// TranscriptionService.swift
import Foundation

class TranscriptionService {
    /// Transcribe a local audio file using the coli CLI.
    /// - Parameter url: Path to .wav / .m4a / .mp3 / .aac file
    /// - Returns: Transcribed string, or nil on failure
    func transcribe(url: URL) async throws -> String {
        return try await withCheckedThrowingContinuation { continuation in
            let process = Process()
            process.executableURL = coliExecutableURL()
            process.arguments = ["transcribe", url.path]

            let pipe = Pipe()
            process.standardOutput = pipe
            process.standardError = Pipe()

            process.terminationHandler = { _ in
                let data = pipe.fileHandleForReading.readDataToEndOfFile()
                let result = String(data: data, encoding: .utf8)?
                    .trimmingCharacters(in: .whitespacesAndNewlines) ?? ""
                if result.isEmpty {
                    continuation.resume(throwing: TranscriptionError.emptyResult)
                } else {
                    continuation.resume(returning: result)
                }
            }
            do {
                try process.run()
           

Related in Image & Video