# NibbleAI > AI-powered tools for your Obsidian vault — speech-to-text, proofreading, title generation, property filling, and more. [![Obsidian plugin](https://img.shields.io/badge/Obsidian-plugin-blue?logo=obsidian)](https://obsidian.md) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE) NibbleAI is a central hub for small, practical AI-assisted tasks inside Obsidian. Instead of installing a dozen single-purpose plugins, NibbleAI gives you one consistent interface with shared configuration, a unified AI service, and a growing set of capabilities. --- ## Features ### 🎙️ Speech-to-Text (Transcription) Record audio directly in Obsidian or upload existing audio/video files, and get instant transcripts via OpenAI Whisper (or any compatible API — Groq, Azure, etc.). - **Record** with your microphone using the built-in recorder - **Upload** audio/video files from disk - **Transcribe** existing audio files via the file context menu - **Post-process** transcripts with an LLM to fix grammar, remove filler words, and format as Markdown - **Auto-generate** note filenames from the transcript content - **Template system** for note content (`{{date}}`, `{{time}}`, `{{title}}`, `{{transcription}}`, `{{audioFile}}`) ### ✍️ Proofreading Fix punctuation and grammar of selected text with a single command or right-click. - **Prompt injection resistant** — the built-in system prompt explicitly guards against prompt injection attacks in the text being proofread - **Smart quote replacement** — straight quotes → curly quotes (except in code blocks) - Works with any OpenAI-compatible provider (OpenRouter, OpenAI, etc.) ### 🏷️ Title Generation Generate a descriptive title for the current note with one command. Choose how to apply it: - **Rename the file** — the note's filename becomes the generated title - **Set a frontmatter property** — adds or updates a `title:` field in the YAML frontmatter ### 📋 Property Filling Fill any frontmatter property with AI-generated content. Built-in quick commands for common properties: - **Fill any property** — prompts you for the property name - **Fill "summary"** — one-click command - **Fill "tags"** — one-click command - Customizable generation prompt with `{property}` placeholder --- ## Installation ### From Obsidian Community Plugins (once published) 1. Open **Settings** → **Community plugins** 2. Disable **Safe mode** 3. Click **Browse** and search for "NibbleAI" 4. Install and **Enable** ### Manual Installation 1. Download the latest release from the [Releases page](https://github.com/your-username/nibbleai/releases) 2. Extract the folder to `YourVault/.obsidian/plugins/nibbleai/` 3. Enable the plugin in **Settings** → **Community plugins** ### Build from Source ```bash git clone https://github.com/your-username/nibbleai.git cd nibbleai npm install npm run build ``` Then copy the `main.js`, `manifest.json`, and `styles.css` to your vault's plugins folder. --- ## Getting Started ### 1. Configure API Keys Open **Settings** → **NibbleAI** and add at least one API key: | Key | Used For | |-----|----------| | **Transcription API Key** | Whisper transcription (OpenAI, Groq, Azure) | | **OpenAI API Key** | Proofreading, title generation, property filling, post-processing *(recommended: OpenRouter)* | | **Anthropic API Key** | Post-processing with Claude models | > **Tip:** For proofreading, title generation, and property filling, an [OpenRouter](https://openrouter.ai/keys) API key with a free model like `google/gemini-2.5-flash-lite` costs nothing and works great. ### 2. Try the Features | Feature | How to Use | |---------|-----------| | **Record audio** | Click the 🤖 ribbon icon, or use the `Start/stop recording` command (`Alt+Q`) | | **Upload audio** | Use the `Upload audio file` command | | **Transcribe existing file** | Right-click an audio file in the file explorer | | **Proofread text** | Select text → right-click → "Fix punctuation and grammar with AI" | | **Generate title** | Use the `Generate title for current note` command | | **Fill property** | Use the `Fill property with AI` command (or the presets for `summary` / `tags`) | --- ## Commands | Command | Icon | Default Hotkey | Description | |---------|------|----------------|-------------| | Start/stop recording | `mic` | `Alt+Q` | Toggle recording on/off | | Upload audio file | `upload` | — | Choose an audio/video file to transcribe | | Pause/resume recording | `pause` | — | Pause or resume an active recording | | Open recording controls | `popup-open` | — | Show the recording modal | | Fix punctuation and grammar | `wand` | — | Proofread selected text with AI | | Generate title for current note | `heading` | — | Generate and apply a title | | Fill property with AI | `pencil` | — | Prompt for a property name, then fill it | | Fill "summary" property | `list` | — | Directly fill the `summary` property | | Fill "tags" property | `tags` | — | Directly fill the `tags` property | --- ## URI Protocol NibbleAI registers the `nibbleai://` protocol handler, allowing external tools to control recording: | URI | Action | |-----|--------| | `obsidian://nibbleai` | Open recording controls | | `obsidian://nibbleai?command=start` | Start recording | | `obsidian://nibbleai?command=stop` | Stop recording | | `obsidian://nibbleai?command=pause` | Pause/resume recording | | `obsidian://nibbleai?command=cancel` | Cancel recording | This is useful for automation tools, Stream Deck, or scripting. --- ## Model Selection Wherever you need to select an AI model (post-processing, proofreading, title generation), NibbleAI provides a **Browse models** button that opens a searchable dialog of available OpenRouter models: - Models are fetched live from `openrouter.ai/api/v1/models` - Free models appear first (marked with a **Free** badge) - Type to filter by name, ID, or description - You can still type a model ID manually if you prefer --- ## Settings Reference ### API Keys Securely stored in your system keychain via Obsidian's SecretStorage. Never written to `data.json`. ### Transcription | Setting | Default | Description | |---------|---------|-------------| | API URL | `https://api.openai.com/v1/audio/transcriptions` | Whisper-compatible endpoint | | Model | `whisper-1` | Transcription model | | Language | *(empty)* | Language hint (auto-detect if empty) | | Prompt | *(empty)* | Boosts accuracy for specific terms | | Cursor context | Off | Send text around cursor as context | | Temperature | `0` | Sampling temperature (0–1) | | Response format | `json` | Output format | ### Recording | Setting | Default | Description | |---------|---------|-------------| | Microphone | Default | Audio input device | | Save audio file | On | Save recording to vault | | Audio save path | *(vault root)* | Folder for audio files | ### Output | Setting | Default | Description | |---------|---------|-------------| | Create note file | On | Create a .md file per transcription | | Note save path | *(vault root)* | Folder for notes | | Note filename template | `{{datetime}}` | Variables: `{{date}}`, `{{time}}`, `{{datetime}}`, `{{title}}` | | Note template | `![[{{audioFile}}]]\n{{transcription}}` | Variables: `{{transcription}}`, `{{audioFile}}`, `{{title}}` | ### Post-Processing | Setting | Default | Description | |---------|---------|-------------| | Enable | Off | Clean up transcripts with an LLM | | Provider | Anthropic | Anthropic, OpenAI, or Custom | | Model | `claude-sonnet-4-20250514` | LLM for cleanup | | Auto-generate title | Off | Create filenames from content | ### Proofreading | Setting | Default | Description | |---------|---------|-------------| | Model | `openai/gpt-4o-mini` | Model for proofreading | | Temperature | `0.2` | Lower = more consistent | | Max tokens | `2000` | Maximum response length | | System prompt | *(built-in)* | Editable with prompt injection protections | ### Title Generation | Setting | Default | Description | |---------|---------|-------------| | Mode | Rename file | Rename file or set frontmatter property | | Max title length | 8 words | Maximum words in generated title | ### Property Filler | Setting | Default | Description | |---------|---------|-------------| | Custom prompt | *(built-in)* | Template with `{property}` placeholder | | Overwrite existing | Off | Replace existing property values | --- ## Architecture ``` NibbleAI/ ├── main.ts # Plugin entry point, commands, events ├── src/ │ ├── SettingsManager.ts # Settings + SecretStorage management │ ├── AIService.ts # Unified AI client (OpenAI + Anthropic) │ ├── ModelBrowser.ts # OpenRouter model suggest modal │ ├── PostProcessor.ts # LLM post-processing for transcripts │ ├── NibbleAISettingsTab.ts # Settings UI │ ├── recorder/ # Audio recording (Timer, StatusBar, Controls, AudioRecorder) │ ├── transcription/ # Whisper API calls + template rendering │ ├── proofreading/ # Proofreading module │ ├── title/ # Title generation module │ └── property/ # Property filling module └── styles.css # Plugin styles ``` All AI calls go through `AIService.callChatCompletion()`, which handles both OpenAI-compatible and Anthropic-native API formats. Each feature module is self-contained and receives the plugin instance for access to settings and the Obsidian API. --- ## Development ```bash # Install dependencies npm install # Build for production npm run build # Watch mode (auto-rebuild on changes) npm run dev # Type-check only npx tsc --noEmit -skipLibCheck ``` Set the `OUTPUT_PATH` environment variable to output `main.js` directly into your vault's plugin directory for fast iteration: ```bash OUTPUT_PATH=/path/to/your/vault/.obsidian/plugins/nibbleai npm run dev ``` --- ## License MIT --- *NibbleAI — small bites of AI for your Obsidian vault.*