mirror of
https://github.com/wiseguru/ReWrite-Voice-Notes.git
synced 2026-07-22 07:49:19 +00:00
Wiki Update
This commit is contained in:
parent
8ec1c93cdf
commit
0773f9ff02
16 changed files with 935 additions and 352 deletions
54
.github/workflows/wiki-sync.yml
vendored
Normal file
54
.github/workflows/wiki-sync.yml
vendored
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
name: Sync wiki
|
||||
|
||||
# Mirrors the canonical docs in wiki/ to the GitHub Wiki repo
|
||||
# (ReWrite-Voice-Notes.wiki.git). The wiki must be enabled and have at
|
||||
# least one page created once in repo settings before the first run.
|
||||
# Edit docs in wiki/; the wiki repo is a generated mirror, never hand-edited.
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
paths:
|
||||
- "wiki/**"
|
||||
- ".github/workflows/wiki-sync.yml"
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
concurrency:
|
||||
group: wiki-sync
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
sync:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Mirror wiki/ to the wiki repo
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
wiki_url="https://x-access-token:${GH_TOKEN}@github.com/${GITHUB_REPOSITORY}.wiki.git"
|
||||
|
||||
git config --global user.name "github-actions[bot]"
|
||||
git config --global user.email "github-actions[bot]@users.noreply.github.com"
|
||||
|
||||
git clone --depth 1 "$wiki_url" wiki-repo
|
||||
|
||||
# Replace the wiki contents with the repo's wiki/ folder,
|
||||
# preserving the wiki repo's own .git directory.
|
||||
find wiki-repo -mindepth 1 -maxdepth 1 ! -name '.git' -exec rm -rf {} +
|
||||
cp -R wiki/. wiki-repo/
|
||||
|
||||
cd wiki-repo
|
||||
git add -A
|
||||
if git diff --cached --quiet; then
|
||||
echo "Wiki already up to date; nothing to push."
|
||||
exit 0
|
||||
fi
|
||||
git commit -m "Sync wiki from ${GITHUB_SHA}"
|
||||
git push origin HEAD
|
||||
25
CLAUDE.md
25
CLAUDE.md
|
|
@ -18,6 +18,31 @@ Some subsystems are documented in depth in linked `docs/` files (currently [docs
|
|||
|
||||
There is a second, user-facing doc to keep in sync: the **template guide** (`DEFAULT_TEMPLATE_GUIDE` in [src/template-guide.ts](src/template-guide.ts)), seeded into the vault by Populate. Any change to the template structure — a new/changed `NoteTemplate` field or frontmatter property, the prompt-assembly order, the default-template set or count, or what the shared core carries — must update the guide in the same change: add the property to its frontmatter table AND give the behavior its own `##` section. See the Templates section for the full rule.
|
||||
|
||||
The user-facing reference docs live in the **wiki** (the [`wiki/` folder](wiki/), mirrored to the GitHub Wiki; see the Wiki section below) and in the slimmed root [README.md](README.md). Both are in the in-sync set: any behavioral change a user can observe (a settings field, a command, a provider, a self-hosting step, a limit, a default-template change) must update the relevant wiki page AND the README quick-start/links if affected, in the same change. The `wiki/` source is canonical; never hand-edit the GitHub Wiki, which is a generated mirror.
|
||||
|
||||
**Reorganize, do not just append.** For every doc in the in-sync set (CLAUDE.md, the linked `docs/` files, the template guide, the wiki, the README), when a change touches documented behavior, first ask whether the doc's *structure* should change to absorb the new material coherently (split an overgrown page, move a topic to a better-fitting page, retitle a section, update `wiki/_Sidebar.md` and `Home.md`'s table of contents) and do that reorganization as part of the same change. Blindly appending a paragraph to the nearest section is a documented anti-pattern here; the goal is docs that stay well-organized as features accrue, not a growing pile of addenda.
|
||||
|
||||
## Wiki
|
||||
|
||||
User-facing documentation lives in [`wiki/`](wiki/) as one Markdown file per page. It is the canonical source; a GitHub Action ([.github/workflows/wiki-sync.yml](.github/workflows/wiki-sync.yml)) mirrors the folder to the separate `ReWrite-Voice-Notes.wiki.git` repo on every push to `master` that touches `wiki/`. The wiki repo is generated output; never edit it by hand. One-time setup (already done): the Wiki feature must be enabled and have a first page created in repo settings before the Action can push.
|
||||
|
||||
GitHub wiki conventions: filenames become page names (spaces as hyphens, no `.md` in links), `Home.md` is the landing page, `_Sidebar.md` is the nav rail, `_Footer.md` the footer. Internal links use the page name, e.g. `[Quick start](Quick-Start)`.
|
||||
|
||||
Page map (keep `_Sidebar.md` and `Home.md`'s contents list in sync when adding/removing pages):
|
||||
- `Home.md`, `_Sidebar.md`, `_Footer.md`: navigation.
|
||||
- `Quick-Start.md`: install, Populate, first note (Daily note example). Overlaps with the README quick-start by design.
|
||||
- `Settings-Reference.md`: every settings section (driven by [src/settings/tab.ts](src/settings/tab.ts)).
|
||||
- `Commands-and-Menus.md`: command palette, ribbon, editor/file menus, Quick Record UI ([src/main.ts](src/main.ts)).
|
||||
- `Creating-Templates.md`: template file format + authoring guide; mirrors the in-vault `Template guide.md` (note that as canonical).
|
||||
- `Providers.md`: provider tables, model selection, base-URL conventions, diarization, context hint, known nouns, recording limits.
|
||||
- `Self-Hosting-Whisper.md`: local whisper.cpp host (mirrors user-facing parts of [docs/WHISPER_HOST.md](docs/WHISPER_HOST.md)).
|
||||
- `Self-Hosting-LLMs.md`: Ollama/llama.cpp local and remote, plus low-spec model recommendations (refresh these as models age).
|
||||
- `Secrets-and-Sync.md`: encryption modes summary + the 7 sync-exclusion recipes.
|
||||
- `Mobile.md`: mobile limitations.
|
||||
- `Troubleshooting.md`: triage that routes into the per-page detail.
|
||||
|
||||
When you move user content out of the README, it goes here, and the README's Documentation section links to it. The deep `docs/` files (DIARIZATION/SECRETS/WHISPER_HOST) stay developer-facing; the wiki summarizes their user-relevant parts and points at them where useful.
|
||||
|
||||
## Commands
|
||||
|
||||
```bash
|
||||
|
|
|
|||
406
README.md
406
README.md
|
|
@ -12,364 +12,66 @@ You bring your own provider keys. Nothing is sent to a ReWrite server; the plugi
|
|||
- Speaker diarization, saved-audio embeds, spoken ad-hoc instructions, known-nouns preservation, and per-run destination overrides.
|
||||
- API keys encrypted at rest (OS secret storage, or an Argon2id/PBKDF2 passphrase) on desktop and mobile.
|
||||
|
||||
## Quick start
|
||||
|
||||
### 1. Install
|
||||
|
||||
**Community plugins (recommended):** in Obsidian, Settings, Community plugins (Restricted mode off), Browse, search "ReWrite (Voice Notes)", Install, Enable.
|
||||
|
||||
**Manual install:** download `main.js`, `manifest.json`, and `styles.css` from the [latest release](https://github.com/WiseGuru/ReWrite-Voice-Notes/releases), drop them into `<YourVault>/.obsidian/plugins/rewrite-voice-notes/`, then enable the plugin in Community plugins.
|
||||
|
||||
### 2. Configure a provider
|
||||
|
||||
Open Settings, ReWrite (Voice Notes). Configure the profile active on this device: pick a transcription provider (audio to text) and an LLM provider (cleanup), enter the API keys, and choose a model for each. The first key you save sets up encryption at rest. Text-only? An LLM alone is enough.
|
||||
|
||||
### 3. Populate templates
|
||||
|
||||
In Settings, Templates, click **Populate**. This seeds `ReWrite/Templates/` with 10 starter templates, plus `SharedCore.md`, `AssistantPrompt.md`, `KnownNouns.md`, and a `Template guide.md`. It is non-destructive.
|
||||
|
||||
### 4. Create your first note
|
||||
|
||||
Click the **mic ribbon icon** (or run the **Open** command), pick the **Daily note** template, then **Record** your voice or **Paste** a transcript. The plugin transcribes, cleans the text, and writes a new dated note (Calendar / Goals / Tasks pulled out, then a Braindump). Recorded audio is saved to your attachments folder and linked back with an `![[...]]` embed.
|
||||
|
||||
The full step-by-step, including faster capture and reprocessing existing audio, is in the [Quick start](https://github.com/WiseGuru/ReWrite-Voice-Notes/wiki/Quick-Start) wiki page.
|
||||
|
||||
## Tested providers
|
||||
|
||||
ReWrite ships adapters for every provider listed below, but only some have been exercised end to end so far. "Tested" means a maintainer has run the full record/transcribe/cleanup/insert flow against that service. "Untested" means the adapter is implemented to the provider's documented API shape but has not yet been verified against a live account. Untested does not mean broken; it means unverified, so treat reports of issues there as expected and welcome.
|
||||
|
||||
### Transcription
|
||||
|
||||
| Provider | Status |
|
||||
| --- | --- |
|
||||
| Local whisper.cpp (plugin-managed) | ✅ Tested |
|
||||
| Mistral Voxtral | ✅ Tested |
|
||||
| AssemblyAI | ✅ Tested |
|
||||
| OpenAI Whisper | Untested |
|
||||
| OpenAI-compatible (whisper.cpp, faster-whisper-server) | Untested |
|
||||
| Groq | Untested |
|
||||
| Deepgram | Untested |
|
||||
| Rev.ai | Untested |
|
||||
|
||||
### LLM (cleanup)
|
||||
|
||||
| Provider | Status |
|
||||
| --- | --- |
|
||||
| Anthropic Claude | ✅ Tested |
|
||||
| Mistral | ✅ Tested |
|
||||
| OpenAI-compatible (Ollama, LM Studio) | ✅ Tested (local Ollama) |
|
||||
| OpenAI GPT | Untested |
|
||||
| Google Gemini | Untested |
|
||||
| DeepSeek / Kimi / Qwen / GLM (cloud OpenAI-compatible) | Untested |
|
||||
|
||||
## Cloud OpenAI-compatible LLMs (DeepSeek, Kimi, Qwen, GLM)
|
||||
|
||||
Many cloud LLM services speak the same `/chat/completions` dialect as OpenAI, so they work through the
|
||||
**OpenAI-compatible** LLM provider with no extra setup. In a profile, set LLM provider to "OpenAI-compatible
|
||||
(cloud or local)", paste the base URL from the table below, type a model name, and enter your API key.
|
||||
|
||||
| Provider | LLM base URL | Example models |
|
||||
| --- | --- | --- |
|
||||
| DeepSeek | `https://api.deepseek.com/v1` | `deepseek-chat`, `deepseek-reasoner` |
|
||||
| Kimi (Moonshot) | `https://api.moonshot.ai/v1` | `kimi-k2-0905-preview`, `moonshot-v1-32k` |
|
||||
| Qwen (DashScope) | `https://dashscope-intl.aliyuncs.com/compatible-mode/v1` | `qwen-max`, `qwen-plus` |
|
||||
| Zhipu GLM | `https://open.bigmodel.cn/api/paas/v4` | `glm-4-plus` |
|
||||
|
||||
Notes:
|
||||
|
||||
- The base URL must include the version path (`/v1`, `/compatible-mode/v1`, etc.); the adapter appends
|
||||
`/chat/completions` to whatever you enter.
|
||||
- The OpenAI-compatible provider has no model dropdown or Refresh button, so type the model ID by hand
|
||||
(the dropdowns above are just examples; consult the provider's docs for the current list).
|
||||
- The URLs above are the international endpoints. China-region accounts can substitute the mainland
|
||||
endpoints instead, e.g. `https://api.moonshot.cn/v1` (Kimi) and
|
||||
`https://dashscope.aliyuncs.com/compatible-mode/v1` (Qwen).
|
||||
|
||||
## Using ReWrite
|
||||
|
||||
Once you have configured at least one transcription and one LLM provider (or just an LLM, for text-only flows), the day-to-day flow is:
|
||||
|
||||
- **Open the modal** with the ribbon mic icon, the "Open" command, or a hotkey you bind to it. Pick a template, then **Record** your voice, **Paste** an existing transcript, or pull text **From note**. The output is cleaned to the template's format and inserted at the cursor, appended to the current note, or written to a new note. When you record, the original audio is saved to your attachments folder and linked back into the result with an `![[...]]` embed.
|
||||
- **Quick Record** captures with no modal: ribbon, command palette, or hotkey. "Quick record (last used)" uses your last template; "Quick record (set template)" uses the one you pin in settings. Press again to stop.
|
||||
- **Process text with template** runs any template over the current selection (or the whole note if nothing is selected), no audio needed, from the command palette or the editor right-click menu.
|
||||
- **Reprocess audio** reruns the pipeline over an audio file already in your vault, from the command palette, the file-explorer right-click menu, or by placing the cursor inside an `![[audio]]` embed. Handy for retrying with a different template or provider.
|
||||
|
||||
Long-form audio (lectures, meetings, interviews, podcasts) uses the very same pipeline: drop the file anywhere in your vault and **Reprocess** it with the **Lecture** or **Podcast** template. For multi-hour recordings choose a provider with a high ceiling such as **AssemblyAI** or **Rev.ai** (OpenAI Whisper and Groq cap at 25 MB, Mistral Voxtral at 30 minutes), and turn on **Identify speakers** in the profile's transcription settings to get `Speaker A:` / `Speaker B:` labels preserved through cleanup. Only process audio you have the right to use; downloading third-party content (e.g. from YouTube) without permission may violate its terms or copyright.
|
||||
|
||||
## Install
|
||||
|
||||
### Obsidian community plugins (recommended)
|
||||
|
||||
1. In Obsidian, open Settings, Community plugins, and turn off Restricted mode if it is on.
|
||||
2. Click Browse, search for "ReWrite (Voice Notes)", and click Install, then Enable.
|
||||
3. Open Settings, ReWrite (Voice Notes), enter at least one provider API key, and pick a model for both the transcription and LLM provider.
|
||||
|
||||
### Manual install (latest release)
|
||||
|
||||
If the plugin is not yet listed, or you want a specific build:
|
||||
|
||||
1. Download `main.js`, `manifest.json`, and `styles.css` from the latest entry on the GitHub Releases page.
|
||||
2. Create the folder `<YourVault>/.obsidian/plugins/rewrite-voice-notes/`.
|
||||
3. Copy the three files into that folder.
|
||||
4. In Obsidian, go to Settings, Community plugins, and enable "ReWrite (Voice Notes)". (Make sure Restricted mode is off.)
|
||||
5. Open Settings, ReWrite (Voice Notes), enter at least one provider API key, and pick a model for both the transcription and LLM provider.
|
||||
|
||||
### Building from source
|
||||
|
||||
```bash
|
||||
git clone https://github.com/<your-fork>/rewrite-voice-notes.git
|
||||
cd rewrite-voice-notes
|
||||
npm install
|
||||
npm run build
|
||||
```
|
||||
|
||||
`main.js`, `styles.css`, and `manifest.json` will be at the repo root. Copy them into your vault as described above.
|
||||
|
||||
## Plugin map
|
||||
|
||||
### Commands
|
||||
|
||||
All commands are available from the command palette; most also have a UI entry point.
|
||||
|
||||
| Command | What it does |
|
||||
| --- | --- |
|
||||
| Open | Opens the main modal with your last-used template selected. Also the ribbon mic icon. |
|
||||
| Quick record (last used) | Starts recording immediately with a floating mini-UI, using the last-used template. Press again to stop. |
|
||||
| Quick record (set template) | Same one-shot capture, but always uses the template you pin in settings. |
|
||||
| Process text with template | Runs a template over the editor selection (or whole note). Also on the editor right-click menu ("ReWrite with template..."). |
|
||||
| Reprocess audio file with template | Reruns the pipeline over an audio file already in the vault. Also on the file-explorer and editor menus. |
|
||||
| Start whisper host / Stop whisper host | Starts or stops the local whisper.cpp server (desktop, when the active profile uses it). |
|
||||
|
||||
A status-bar item shows the local whisper.cpp server's live state on desktop when that provider is active.
|
||||
|
||||
### Vault files
|
||||
|
||||
The plugin keeps its editable configuration as Markdown files in your vault (defaults shown; all paths are configurable). Click **Populate** in settings to create them on first run.
|
||||
|
||||
| Path | Purpose |
|
||||
| --- | --- |
|
||||
| `ReWrite/Templates/` | One Markdown file per template (YAML frontmatter + a prompt body). Sorted by filename, so prefix with `01-`, `02-`, etc. to reorder. |
|
||||
| `ReWrite/SharedCore.md` | The cleanup ground rules prepended to every template prompt. Edit once to change the baseline; delete to turn it off. |
|
||||
| `ReWrite/AssistantPrompt.md` | The persona and standing instructions prefaced to the cleanup step. |
|
||||
| `ReWrite/KnownNouns.md` | Proper nouns the LLM should preserve verbatim, with optional misheard variants. |
|
||||
| `ReWrite/Template guide.md` | A human-facing explanation of the template format. Never sent to an LLM. |
|
||||
| `ReWrite/Template update report.md` | Written by the Update button when a shipped default has changed and needs your review. |
|
||||
| Attachments folder | Saved recordings (Obsidian's attachment location, or a folder you configure). Each is linked into the output via `![[...]]`. |
|
||||
|
||||
### Templates
|
||||
|
||||
The 10 bundled templates are starting points; they are just files, so edit, rename, reorder, or add your own. `newFile` templates can have the LLM fill in frontmatter properties and generate the filename from the content.
|
||||
|
||||
| Template | Behavior |
|
||||
| --- | --- |
|
||||
| General cleanup | Light prose polishing (grammar, fillers); inserts at the cursor. |
|
||||
| Todo list | Turns spoken items into a checklist. |
|
||||
| Daily note | New file named by date; fills Calendar / Goals / Tasks, then a Braindump of the full cleaned transcript. |
|
||||
| Meeting notes | New file; offers a context hint; sets subject / participants / date properties and a content-derived title. |
|
||||
| Meeting transcript | Like Meeting notes, but forces diarization on for speaker-labeled input. |
|
||||
| Idea capture | Quick capture of a single idea. |
|
||||
| Lecture | New file; restructures a talk into Summary / Key concepts / Definitions / etc.; subject / lecturer / course properties + title. |
|
||||
| Podcast | New file; tolerates diarized or flat input; podcast / episode / host / guests properties + title. |
|
||||
| Guides | New file; turns a walkthrough into strict two-level how-to steps; topic / tool properties + title. |
|
||||
| Book log | New file; short book-log body; title / author / series properties + content title. |
|
||||
|
||||
Diarization, when enabled on a capable provider, adds `Speaker X:` prefixes that the cleanup step preserves.
|
||||
|
||||
## Self Hosting
|
||||
|
||||
ReWrite can run with no cloud dependency by combining a local LLM for cleanup with the plugin-managed local whisper.cpp server for transcription.
|
||||
|
||||
### Local LLM (Ollama / llama.cpp)
|
||||
|
||||
Local LLM servers that speak the OpenAI `/chat/completions` dialect work through the **OpenAI-compatible** LLM provider. In a profile, set LLM provider to "OpenAI-compatible (cloud or local)", then fill in the base URL and model.
|
||||
|
||||
- **Ollama**: run `ollama serve` and `ollama pull <model>` (e.g. `llama3.1`). Base URL `http://localhost:11434/v1`, model = the pulled name. Ollama ignores the API key, so any non-empty placeholder is fine.
|
||||
- **llama.cpp**: run `llama-server -m <model.gguf>`. Base URL `http://localhost:8080/v1`, model = whatever name the server reports.
|
||||
|
||||
The base URL must include the version path (`/v1`); the adapter appends `/chat/completions` to whatever you enter. Pair this with the local whisper.cpp server below for a setup where nothing leaves your machine.
|
||||
|
||||
### Local whisper.cpp server (desktop, optional)
|
||||
|
||||
If you want fully on-device transcription with no network calls, the plugin can spawn a [whisper.cpp](https://github.com/ggerganov/whisper.cpp) `whisper-server` binary that you supply. The plugin only reads the absolute paths you configure; it never downloads binaries, never looks them up on PATH, and never spawns anything you did not explicitly point it at. Desktop only.
|
||||
|
||||
#### Disclosure
|
||||
|
||||
When you click Start in settings, the plugin launches whisper-server as a child process and communicates with it over loopback (`http://127.0.0.1:<port>`). The process is captured in a ring-buffered log you can view in settings. When you click Stop, or when the plugin is unloaded, the process is terminated. No code is downloaded or executed beyond the binary you provide.
|
||||
|
||||
**Network exposure**: whisper-server has no authentication and no TLS, so anyone who can reach its port can submit audio and exercise its native audio-decoding code. To keep it private, ReWrite always passes `--host 127.0.0.1` (loopback only) and **refuses to start** if you put a `--host` pointing at a non-loopback interface (such as `0.0.0.0` or a LAN IP) in Extra args. If you run whisper-server yourself from a terminal instead of letting the plugin manage it, bind it to `127.0.0.1` the same way; do not expose it to your network unless you have put your own authenticating proxy in front of it.
|
||||
|
||||
#### Setup
|
||||
|
||||
1. Obtain a `whisper-server` binary:
|
||||
- **Windows**: download the latest `whisper-bin-x64.zip` (CPU) or `whisper-cublas-12.4.0-bin-x64.zip` (NVIDIA GPU) from the [whisper.cpp releases page](https://github.com/ggerganov/whisper.cpp/releases), unzip somewhere stable (e.g. `C:\Tools\whisper.cpp\`), and use the path to `whisper-server.exe` inside that folder.
|
||||
- **macOS**: the easiest path is Homebrew (`brew install whisper-cpp`), which installs a `whisper-server` binary; `which whisper-server` will show its absolute path. Or build from source the same way as Linux below.
|
||||
- **Linux**: there are no official Linux binaries on the releases page, so you build from source once. See "Building whisper-server on Linux" just below.
|
||||
2. Download a GGML model file. Two sources work out of the box:
|
||||
- **Upstream GGML models** from [Hugging Face](https://huggingface.co/ggerganov/whisper.cpp/tree/main), e.g. `ggml-base.en.bin`, `ggml-small.bin`, `ggml-large-v3.bin`. Larger models are more accurate and slower.
|
||||
- **FUTO whisper-acft models** (see the next section). These are quantized, finetuned variants that support dynamic audio context; they load with the same `-m` flag as upstream models.
|
||||
3. Open ReWrite settings, scroll to "Local whisper.cpp server (desktop)", and fill in:
|
||||
- Binary path: absolute path to `whisper-server` (or `whisper-server.exe` on Windows).
|
||||
- Model path: absolute path to the `.bin` file.
|
||||
- Port: defaults to 8080.
|
||||
4. Click Start. The status indicator transitions from Stopped to Starting to Running. View log shows whisper-server's stdout/stderr if startup fails.
|
||||
5. In the profile you want to use it from, set Transcription provider to "Local whisper.cpp (desktop only)". The Transcription model field is decorative for this provider; whisper-server uses whichever model file is loaded at startup.
|
||||
|
||||
#### Building `whisper-server` on Linux
|
||||
|
||||
whisper.cpp doesn't publish prebuilt Linux binaries, so you need to compile it once. The build is quick (under a minute on a modern laptop) and produces a single executable that you then point the plugin at.
|
||||
|
||||
1. Install the toolchain. Pick the line for your distro:
|
||||
- Debian / Ubuntu / Mint: `sudo apt update && sudo apt install -y build-essential cmake git`
|
||||
- Fedora / RHEL: `sudo dnf install -y gcc-c++ make cmake git`
|
||||
- Arch / Manjaro: `sudo pacman -S --needed base-devel cmake git`
|
||||
- openSUSE: `sudo zypper install -y gcc-c++ make cmake git`
|
||||
|
||||
2. Clone and build:
|
||||
|
||||
```bash
|
||||
git clone https://github.com/ggerganov/whisper.cpp.git
|
||||
cd whisper.cpp
|
||||
cmake -B build -DCMAKE_BUILD_TYPE=Release
|
||||
cmake --build build -j --config Release
|
||||
```
|
||||
|
||||
The default build includes the `server` example, so no extra flags are needed. If you have an NVIDIA GPU and want CUDA acceleration, replace the first `cmake` line with `cmake -B build -DCMAKE_BUILD_TYPE=Release -DGGML_CUDA=ON` (requires the CUDA toolkit installed; the build takes substantially longer).
|
||||
|
||||
3. After the build finishes, the binary lives at:
|
||||
|
||||
```
|
||||
<path-to-clone>/build/bin/whisper-server
|
||||
```
|
||||
|
||||
Copy or symlink it somewhere stable (e.g. `~/.local/bin/whisper-server`) if you want to keep the absolute path short. Make sure it is executable: `chmod +x build/bin/whisper-server`.
|
||||
|
||||
4. Use that absolute path as Binary path in the plugin's "Local whisper.cpp server (desktop)" settings section. To sanity-check the binary outside the plugin first, run it once from a terminal with a model file: `./build/bin/whisper-server -m /path/to/model.bin --host 127.0.0.1 --port 8080`. You should see `whisper server listening at http://127.0.0.1:8080`. Pass `--host 127.0.0.1` so the unauthenticated server stays bound to loopback and is not reachable from your network. Hit Ctrl-C to stop, then let the plugin manage it from there.
|
||||
|
||||
If `cmake --build` fails with `error: 'std::filesystem' has not been declared` or similar C++17 errors, your distro's default GCC is too old. Install a newer one (`sudo apt install g++-12` on Ubuntu) and rerun the `cmake -B build ...` step with `-DCMAKE_CXX_COMPILER=g++-12` appended.
|
||||
|
||||
#### FUTO whisper-acft models
|
||||
|
||||
[whisper-acft](https://github.com/futo-org/whisper-acft) is a set of Whisper checkpoints finetuned by FUTO so that whisper.cpp's encoder tolerates a dynamic `audio_ctx` (the number of audio frames the encoder processes). With stock Whisper models, lowering `audio_ctx` to match shorter clips makes the decoder unstable; the ACFT models were retrained to handle this gracefully, which can cut latency on short utterances substantially (often a 2x to 4x speedup on the small models, depending on hardware).
|
||||
|
||||
The published checkpoints are quantized to `q8_0` and ship in the same GGML container that whisper.cpp's `-m` flag already accepts, so no special build of whisper-server is required. You just need a whisper.cpp version recent enough to recognize the `-ac` / `--audio-context` flag (any reasonably current `whisper-server` release does).
|
||||
|
||||
1. Pick a model and download the `.bin` directly. English-only checkpoints are smaller and faster for English input; multilingual handles other languages but is slightly slower at the same size.
|
||||
|
||||
English-only:
|
||||
- tiny.en: `https://voiceinput.futo.org/VoiceInput/tiny_en_acft_q8_0.bin`
|
||||
- base.en: `https://voiceinput.futo.org/VoiceInput/base_en_acft_q8_0.bin`
|
||||
- small.en: `https://voiceinput.futo.org/VoiceInput/small_en_acft_q8_0.bin`
|
||||
|
||||
Multilingual:
|
||||
- tiny: `https://voiceinput.futo.org/VoiceInput/tiny_acft_q8_0.bin`
|
||||
- base: `https://voiceinput.futo.org/VoiceInput/base_acft_q8_0.bin`
|
||||
- small: `https://voiceinput.futo.org/VoiceInput/small_acft_q8_0.bin`
|
||||
|
||||
Save the file anywhere you like (the same folder as your other GGML models is fine). Verify the download finished cleanly before pointing the plugin at it; a truncated `.bin` will fail to load with a cryptic error in the log tail.
|
||||
|
||||
2. In ReWrite settings under "Local whisper.cpp server (desktop)", set Model path to the absolute path of the FUTO `.bin` you just downloaded. Binary path and Port are unchanged from the standard setup above.
|
||||
|
||||
3. Set Extra args (in the "Local whisper.cpp server (desktop)" section) to:
|
||||
|
||||
```
|
||||
-ac 768
|
||||
```
|
||||
|
||||
Do not add a `--host` here pointing at a non-loopback interface; ReWrite binds the server to `127.0.0.1` and will refuse to start otherwise (the server is unauthenticated).
|
||||
|
||||
`-ac` (alias `--audio-context`) caps the encoder context at the given number of mel frames. Lower values run faster but only stay accurate on ACFT-finetuned models, which is the whole point of using them. A few starting points:
|
||||
|
||||
- `-ac 768` is a sensible default for short to medium clips (roughly up to ~15 s). Drop to `-ac 512` for short voice memos under ~10 s.
|
||||
- `-ac 1500` (the whisper.cpp default for 30 s of audio) disables the speedup. Use this if you regularly dictate longer than ~20 s and notice the tail being cut off.
|
||||
- You can pass additional flags on the same line, space-separated, e.g. `-ac 768 -t 4` to also cap CPU threads at 4.
|
||||
|
||||
4. Click Start (or Restart if the host was already running). The status pill should return to Running and the View log output should show whisper-server loading the ACFT model file. From the consuming profile, the Local whisper.cpp transcription provider needs no changes; it forwards the audio over the same `/v1/audio/transcriptions` endpoint and the `-ac` value is applied server-side.
|
||||
|
||||
If transcription quality drops noticeably (truncated sentences, missing trailing words), raise `-ac` toward 1500 until it stabilizes. The right value depends on how long your typical recording is; there is no single best number.
|
||||
|
||||
#### Troubleshooting
|
||||
|
||||
- **Port already in use**: another process is bound to the configured port. Change the port (or stop the other process). The plugin will not kill processes it did not start.
|
||||
- **Antivirus quarantine on Windows**: Windows Defender or third-party AV may flag `whisper-server.exe` on first run. The plugin cannot work around this; whitelist the binary in your AV settings.
|
||||
- **Permission denied on macOS or Linux**: ensure the binary is executable (`chmod +x whisper-server`).
|
||||
- **Process did not become ready within 5 s**: the model failed to load (file path wrong, file corrupted, RAM exhausted). The log tail will show whisper.cpp's error.
|
||||
- **`unknown argument: -ac` (or `--audio-context`) in the log**: your `whisper-server` build predates the dynamic audio-context flag. Update to a current whisper.cpp release, or remove the `-ac` value from Extra args (you can still use the FUTO model files without the flag, you just lose the latency benefit).
|
||||
- **FUTO model loads but transcripts are truncated or jumbled**: `-ac` is set too low for the length of audio you are dictating. Raise it (e.g. `768` to `1024` to `1500`) until the output is stable.
|
||||
|
||||
## Excluding `secrets.json.nosync` from sync
|
||||
|
||||
API keys are stored in `<YourVault>/.obsidian/plugins/rewrite-voice-notes/secrets.json.nosync`, separately from the rest of the plugin's settings.
|
||||
|
||||
The plugin supports two at-rest encryption modes, selectable in settings under "API key encryption". There is no unencrypted option:
|
||||
|
||||
- **Obsidian secret storage** (`secretStorage`): the default when available (Obsidian 1.11.4 or later with a working OS secret store). Keys are stored in Obsidian's built-in secret store, which encrypts them at rest using your operating system's keychain and is shared across plugins. Because it is an Obsidian-managed store, **if you use Obsidian Sync these keys may sync across your devices** (a convenience, but note your keys then leave the single-device boundary). The plugin runs a round-trip self-test and falls back to passphrase on a device with no working OS secret store (for example Linux without a keyring). In this mode the keys do **not** live in `secrets.json.nosync` (that file only records which mode is in use).
|
||||
- **Passphrase**: AES-GCM encryption with a key derived from a passphrase you set, using Argon2id (a memory-hard key-derivation function) or PBKDF2 on devices that cannot run Argon2id. Works on every platform including mobile, the keys stay on the device (stored encrypted in `secrets.json.nosync`), and the blob is portable across devices (you re-enter the passphrase to unlock on each one). When you set a passphrase the plugin enforces a minimum strength and offers a one-click generator that produces a strong 6-word passphrase. On devices where Obsidian secret storage is unavailable, setting a passphrase is required before any key can be saved.
|
||||
|
||||
If you use **passphrase mode** and do not want the encrypted key file copied around, **you can exclude `secrets.json.nosync` from any vault sync mechanism** and enter keys once per device. Configure the exclusion **before the first sync**, since files already uploaded usually remain on the remote. (In Obsidian secret storage mode this file holds no keys, so excluding it has no effect on the keys themselves.)
|
||||
|
||||
The path to exclude is always:
|
||||
|
||||
```
|
||||
.obsidian/plugins/rewrite-voice-notes/secrets.json.nosync
|
||||
```
|
||||
|
||||
### Obsidian Sync (official)
|
||||
|
||||
Obsidian Sync excludes folders, not individual files (Settings, Sync, Excluded folders). You have two options:
|
||||
|
||||
- Exclude the entire `.obsidian/plugins/rewrite-voice-notes` folder and accept that you will lose template/profile sync (`data.json` lives there too).
|
||||
- Or sync the folder and accept that the encrypted `secrets.json.nosync` blob will be uploaded; on other devices it will fail to decrypt and the plugin will treat it as no key set, prompting you to enter the key again.
|
||||
|
||||
### Syncthing
|
||||
|
||||
Add to `.stignore` in the synced folder root:
|
||||
|
||||
```
|
||||
// ReWrite plugin secrets, never sync API keys
|
||||
.obsidian/plugins/rewrite-voice-notes/secrets.json.nosync
|
||||
```
|
||||
|
||||
If the vault is not at the Syncthing folder root, omit the leading slash from any patterns.
|
||||
|
||||
### Resilio Sync
|
||||
|
||||
Add this line to `.sync/IgnoreList` on each peer:
|
||||
|
||||
```
|
||||
.obsidian/plugins/rewrite-voice-notes/secrets.json.nosync
|
||||
```
|
||||
|
||||
### Git / GitHub
|
||||
|
||||
Add to the vault's `.gitignore`:
|
||||
|
||||
```gitignore
|
||||
# ReWrite plugin, never commit API keys
|
||||
.obsidian/plugins/rewrite-voice-notes/secrets.json.nosync
|
||||
```
|
||||
|
||||
If you have already committed it:
|
||||
|
||||
```bash
|
||||
git rm --cached .obsidian/plugins/rewrite-voice-notes/secrets.json.nosync
|
||||
git commit -m "remove rewrite-voice-notes secrets from tracking"
|
||||
```
|
||||
|
||||
### Dropbox
|
||||
|
||||
Dropbox has no ignore-file mechanism. Use Selective Sync:
|
||||
|
||||
1. Open the Dropbox desktop app.
|
||||
2. Preferences, Sync, Selective Sync.
|
||||
3. Deselect the `rewrite-voice-notes` plugin folder, or use file-level exclusions if your Dropbox plan supports them.
|
||||
|
||||
Alternatively, delete `secrets.json.nosync` from Dropbox via the web interface after setup; the plugin will recreate it locally when you next enter keys.
|
||||
|
||||
### iCloud Drive
|
||||
|
||||
No configuration needed. iCloud Drive automatically skips any file or folder whose name ends in `.nosync`, which is why the plugin uses that suffix.
|
||||
|
||||
### FolderSync (Android)
|
||||
|
||||
In each sync pair, go to Filters, Excluded files, and add the pattern:
|
||||
|
||||
```
|
||||
secrets.json.nosync
|
||||
```
|
||||
|
||||
## Mobile limitations
|
||||
|
||||
Obsidian on iOS and Android runs in a constrained WebView. A few things behave differently from desktop:
|
||||
|
||||
- **Screen-off during recording**: mobile WebViews suspend (and stop `MediaRecorder` capture) when the screen sleeps. To counter this, the plugin holds a screen wake lock for the duration of an active recording on both iOS and Android, so screen-off mid-recording is largely mitigated on supported OS versions. It is best-effort: on older WebViews, in an insecure context, or if the OS denies the request, it silently falls back to the old behavior, so keeping the screen on (or using the Paste tab with an OS-level dictation keyboard) is still the safe habit.
|
||||
- **Mobile encryption**: if your Obsidian version provides secret storage on mobile (1.11.4 or later), keys use it just like on desktop. Otherwise the plugin prompts you to set a passphrase before any key can be saved, and keys are then encrypted with Argon2id/PBKDF2 AES-GCM. The `secrets.json.nosync` file (which holds encrypted keys only in passphrase mode) uses the `.nosync` filename so iCloud Drive will skip it; for other sync tools, apply the exclusion rules above.
|
||||
- **Recording size limit**: each transcription provider enforces its own ceiling (OpenAI Whisper and Groq are the tightest at 25 MB; AssemblyAI, Deepgram, and Rev.ai allow gigabytes). These are provider-API limits, not Obsidian ones, and are most likely to bite on long mobile recordings with the 25 MB providers.
|
||||
|
||||
## Known limitations (v1)
|
||||
"Tested" means a maintainer has run the full record/transcribe/cleanup/insert flow against that service. "Untested" means the adapter is implemented to the provider's documented API shape but not yet verified against a live account (unverified, not broken). For setup of each, see [Providers](https://github.com/WiseGuru/ReWrite-Voice-Notes/wiki/Providers).
|
||||
|
||||
| Transcription | Status | | LLM (cleanup) | Status |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| Local whisper.cpp (plugin-managed) | ✅ Tested | | Anthropic Claude | ✅ Tested |
|
||||
| Mistral Voxtral | ✅ Tested | | Mistral | ✅ Tested |
|
||||
| AssemblyAI | ✅ Tested | | OpenAI-compatible (Ollama, LM Studio) | ✅ Tested (local Ollama) |
|
||||
| OpenAI Whisper | Untested | | OpenAI GPT | Untested |
|
||||
| OpenAI-compatible (whisper.cpp) | Untested | | Google Gemini | Untested |
|
||||
| Groq | Untested | | DeepSeek / Kimi / Qwen / GLM | Untested |
|
||||
| Deepgram | Untested | | | |
|
||||
| Rev.ai | Untested | | | |
|
||||
|
||||
## Documentation
|
||||
|
||||
Full documentation lives in the [wiki](https://github.com/WiseGuru/ReWrite-Voice-Notes/wiki):
|
||||
|
||||
- [Quick start](https://github.com/WiseGuru/ReWrite-Voice-Notes/wiki/Quick-Start) - install to first note.
|
||||
- [Settings reference](https://github.com/WiseGuru/ReWrite-Voice-Notes/wiki/Settings-Reference) - every setting, section by section.
|
||||
- [Commands and menus](https://github.com/WiseGuru/ReWrite-Voice-Notes/wiki/Commands-and-Menus) - command palette, ribbon, menus, Quick Record.
|
||||
- [Creating templates](https://github.com/WiseGuru/ReWrite-Voice-Notes/wiki/Creating-Templates) - the template format and a full authoring guide.
|
||||
- [Providers](https://github.com/WiseGuru/ReWrite-Voice-Notes/wiki/Providers) - providers, models, diarization, context hints, known nouns, limits.
|
||||
- [Self-hosting: whisper.cpp](https://github.com/WiseGuru/ReWrite-Voice-Notes/wiki/Self-Hosting-Whisper) - on-device transcription.
|
||||
- [Self-hosting: local and remote LLMs](https://github.com/WiseGuru/ReWrite-Voice-Notes/wiki/Self-Hosting-LLMs) - Ollama / llama.cpp, locally or remote, with model picks.
|
||||
- [Secrets and sync](https://github.com/WiseGuru/ReWrite-Voice-Notes/wiki/Secrets-and-Sync) - key encryption and excluding `secrets.json.nosync` from each sync tool.
|
||||
- [Mobile](https://github.com/WiseGuru/ReWrite-Voice-Notes/wiki/Mobile) - iOS/Android differences.
|
||||
- [Troubleshooting](https://github.com/WiseGuru/ReWrite-Voice-Notes/wiki/Troubleshooting) - triage for common problems.
|
||||
|
||||
These pages are maintained in the [`wiki/` folder](wiki/) of this repo and mirrored to the GitHub Wiki automatically.
|
||||
|
||||
## Known limitations
|
||||
|
||||
- No audio playback or waveform display.
|
||||
- LLM responses are not streamed; you see the cleaned output once the whole response arrives.
|
||||
- No long-audio chunking; clips that exceed the active provider's size or duration limit error out instead of being split.
|
||||
- The OpenAI-compatible transcription endpoint expects a server that mirrors Whisper's `/v1/audio/transcriptions` shape (whisper.cpp, faster-whisper-server). The OpenAI-compatible LLM endpoint expects a `/chat/completions` shape (Ollama, LM Studio, etc.).
|
||||
- Anthropic Claude calls go through Obsidian's `requestUrl`, which bypasses browser CORS. If you reuse the same endpoint from another tool that uses `fetch`, you will need their browser-direct-access header.
|
||||
- Anthropic Claude calls go through Obsidian's `requestUrl`, which bypasses browser CORS.
|
||||
|
||||
## Vault access
|
||||
|
||||
|
|
|
|||
52
wiki/Commands-and-Menus.md
Normal file
52
wiki/Commands-and-Menus.md
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
# Commands and menus
|
||||
|
||||
Every entry point ReWrite adds: command palette commands, the ribbon icon, right-click menus, and the Quick Record floating UI. Bind hotkeys to any command in Obsidian's Hotkeys settings.
|
||||
|
||||
## Command palette
|
||||
|
||||
| Command | What it does |
|
||||
| --- | --- |
|
||||
| **Open** | Opens the main modal with your last-used template selected. Same as the ribbon mic icon. |
|
||||
| **Quick record (last used)** | Starts recording immediately with a floating mini-UI, using the last-used template. Press again (or its hotkey) to stop. |
|
||||
| **Quick record (set template)** | Same one-shot capture, but always uses the template pinned in Settings, Templates, Quick record (set template). If none is pinned, it shows a notice and does nothing. |
|
||||
| **Process text with template** | Runs a template over the current editor selection, or the whole note if nothing is selected. No audio. Progress shows via notices. |
|
||||
| **Reprocess audio file with template** | Reruns the full pipeline over an audio file already in your vault. Opens an audio-file picker, then a template picker. |
|
||||
| **Start whisper host** / **Stop whisper host** | Starts or stops the local whisper.cpp server. Only visible on desktop when relevant (start: active profile uses `whisper-local`; stop: the host is running or starting). See [Self-hosting: whisper.cpp](Self-Hosting-Whisper). |
|
||||
|
||||
## Ribbon and status bar
|
||||
|
||||
- **Mic ribbon icon**: opens the main modal (same as the Open command).
|
||||
- **Whisper status bar item** (desktop only): shows the local whisper.cpp server's live state when the active profile uses it. Click it to start or stop the server.
|
||||
|
||||
## Right-click menus
|
||||
|
||||
- **Editor menu** ("ReWrite with template..."): right-click in a note to run a template over the selection or whole note, the same as the Process text command.
|
||||
- **Editor menu** ("Reprocess audio with template..."): appears only when your cursor sits inside an `![[audio]]` embed; reprocesses that linked audio file.
|
||||
- **File explorer menu** ("Reprocess audio with template..."): right-click an audio file in the file explorer to reprocess it.
|
||||
|
||||
## The main modal
|
||||
|
||||
Opened by the ribbon icon or the Open command. It has:
|
||||
|
||||
- A **template selector** at the top.
|
||||
- Three input tabs: **Record** (capture in Obsidian), **Paste** (paste an existing transcript), and **From note** (pull the active note's selection or whole body).
|
||||
- A collapsible **Destination** control to override, for this run only, where the output goes (cursor / new file / append) without editing the template on disk.
|
||||
- A collapsible **Context** field, shown only for templates that enable it, for one-off background info (speakers, subject, setting). See [Providers](Providers).
|
||||
- An inline **setup card** that blocks recording or pasting until the active profile is configured, with a shortcut to fix it.
|
||||
|
||||
## Quick Record floating UI
|
||||
|
||||
Quick Record skips the modal entirely. When you start it, a small floating panel appears with:
|
||||
|
||||
- A **live timer**.
|
||||
- A **template button** that opens a popover to switch templates for this recording (dismisses on selection, Escape, or outside click).
|
||||
- A **Stop** button, preceded by a **stop-hotkey hint** ("Press <combo> or click Stop") when the command is bound to a hotkey.
|
||||
- A **"No audio detected" warning** if the mic stays silent for a few seconds (a muted or dead mic).
|
||||
|
||||
Both Quick Record commands share one in-flight recording, so either one stops a recording the other started. If the active profile is not configured, or audio capture is unavailable, Quick Record opens the main modal instead. If the pipeline errors after capture, the modal opens so you can retry; the saved audio file is your recovery path.
|
||||
|
||||
## Long-form audio
|
||||
|
||||
Lectures, meetings, interviews, and podcasts use the same pipeline. Drop the file anywhere in your vault and **Reprocess** it with the **Lecture** or **Podcast** template. For multi-hour recordings, choose a provider with a high ceiling such as AssemblyAI or Rev.ai (OpenAI Whisper and Groq cap at 25 MB; Mistral Voxtral at 30 minutes), and turn on **Identify speakers** to keep speaker labels through cleanup. See per-provider limits in [Providers](Providers). Only process audio you have the right to use.
|
||||
|
||||
[Back to Home](Home)
|
||||
111
wiki/Creating-Templates.md
Normal file
111
wiki/Creating-Templates.md
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
# Creating templates
|
||||
|
||||
Templates control how a transcript is cleaned and structured, and where the result goes. They are plain Markdown files in your vault, so you edit, rename, reorder, and create them like any other note.
|
||||
|
||||
The plugin also seeds a copy of this guide into your vault as `ReWrite/Template guide.md` when you Populate. That in-vault copy is the canonical, always-current reference (it ships with the exact version of the plugin you have installed). This page mirrors it for easy browsing; if the two ever differ, trust the in-vault guide.
|
||||
|
||||
## Anatomy of a template
|
||||
|
||||
Each template is one `.md` file in your templates folder (default `ReWrite/Templates/`):
|
||||
|
||||
```markdown
|
||||
---
|
||||
id: my-meeting-notes
|
||||
name: Meeting notes
|
||||
insertMode: newFile
|
||||
newFileFolder: Meetings
|
||||
newFileNameTemplate: Meeting {{date}} {{title}}
|
||||
disableSharedCore:
|
||||
enableContextHint: true
|
||||
diarize:
|
||||
titleFromContent: true
|
||||
noteProperties:
|
||||
subject: One short line naming the meeting's topic.
|
||||
participants: Comma-separated list of people present.
|
||||
date: The meeting date if stated, else today.
|
||||
---
|
||||
|
||||
Turn the transcript into concise meeting notes. Use these sections, omitting any with no content:
|
||||
|
||||
## Summary
|
||||
## Decisions
|
||||
## Action items
|
||||
```
|
||||
|
||||
- **Frontmatter** (between the `---` lines) configures the template.
|
||||
- **Body** (everything after) is the prompt sent to the LLM.
|
||||
|
||||
Files are sorted by filename in the modal and pickers, so prefix names with `01-`, `02-`, etc. to control order. The frontmatter `id` is the identity, so renaming a file does not break the default-template or last-used references.
|
||||
|
||||
## Frontmatter fields
|
||||
|
||||
| Field | Type | Purpose |
|
||||
| --- | --- | --- |
|
||||
| `id` | string | Stable identity. Keep it unique; do not reuse across templates. |
|
||||
| `name` | string | Display name in the modal and pickers. |
|
||||
| `insertMode` | `cursor` / `newFile` / `append` | Where the output goes (see below). |
|
||||
| `newFileFolder` | string | Folder for `newFile` output. |
|
||||
| `newFileNameTemplate` | string | Filename pattern for `newFile`, supports `{{date}}`, `{{time}}`, `{{title}}`. |
|
||||
| `disableSharedCore` | boolean | Set `true` to skip the shared core for this template (opt-out). |
|
||||
| `enableContextHint` | boolean | Set `true` to show the one-off Context field for this template (opt-in). |
|
||||
| `diarize` | boolean | Set `true` to force speaker labels on (only effective on diarization-capable providers). |
|
||||
| `titleFromContent` | boolean | Set `true` to have the LLM name the new file from the content. |
|
||||
| `noteProperties` | map | Frontmatter properties the LLM fills from the content (key = property name, value = instruction). `newFile` only. |
|
||||
|
||||
Note the polarity difference: `disableSharedCore` is an opt-out (set it to turn the shared core OFF for this template), while `enableContextHint`, `diarize`, and `titleFromContent` are opt-ins (set them to turn a feature ON). Populate always writes the four boolean keys as empty stubs so they are discoverable; an empty value means "not set". Obsidian's Properties UI may store an edited boolean as text, so the parser accepts both `true` and the string `"true"`.
|
||||
|
||||
## Insert modes
|
||||
|
||||
- **`cursor`**: inserts at the cursor in the active note. Falls back to `append` when no editor is open.
|
||||
- **`append`**: appends to the current Markdown note. Falls back to `newFile` when no note is open.
|
||||
- **`newFile`**: writes a new note in `newFileFolder`, named by `newFileNameTemplate`.
|
||||
|
||||
Filename tokens (newFile): `{{date}}` and `{{time}}` expand via Obsidian's date formatting; `{{title}}` expands to the LLM-generated title when `titleFromContent` is on (and collapses cleanly when absent). Collisions are resolved per your "On filename collision" setting.
|
||||
|
||||
The per-run Destination control in the modal can override the insert mode for a single run without editing the template on disk.
|
||||
|
||||
## The shared core
|
||||
|
||||
`ReWrite/SharedCore.md` holds baseline cleanup rules (an anti-injection guardrail, general grammar/filler cleanup, and output discipline). At cleanup time the plugin prepends it to your template prompt, so the assembled system prompt reads: shared core, then template prompt, then any spoken ad-hoc instructions, then the context hint, then known nouns, then note-properties instructions.
|
||||
|
||||
Because the shared core is shared, write your template prompt to describe only what is special about this template (the sections, the tone, the format). Do not repeat general cleanup rules. Delete or empty `SharedCore.md` to disable it everywhere; set `disableSharedCore: true` to disable it for one template. A template that opts out runs without the anti-injection guardrail, so the settings tab flags any such template.
|
||||
|
||||
## Note properties
|
||||
|
||||
For `newFile` templates, `noteProperties` asks the LLM to emit a leading YAML block that becomes the note's frontmatter. Author it as a YAML map (property name to instruction). The key order drives both the prompt and the written order. Properties are written only in `newFile` mode (never into an existing note). Example:
|
||||
|
||||
```yaml
|
||||
noteProperties:
|
||||
podcast: The show name.
|
||||
episode: Episode number or title if stated.
|
||||
host: The host's name.
|
||||
guests: Comma-separated guest names.
|
||||
```
|
||||
|
||||
## Note title
|
||||
|
||||
`titleFromContent: true` asks the LLM to generate a title for the new file. It rides the same leading YAML block as note properties (under a reserved key) but is used only for the filename, never written as a frontmatter property. Use it with a `{{title}}` token in `newFileNameTemplate` (for example `Meeting {{date}} {{title}}`), or with no token, in which case the title becomes the whole filename. The plugin hardens the model's output into a safe filename and falls back to the static name if nothing usable remains.
|
||||
|
||||
## Writing a good prompt
|
||||
|
||||
1. **Describe the shape, not the cleanup.** The shared core already handles grammar and fillers. Spend the prompt on structure.
|
||||
2. **Name your sections explicitly.** "Use these sections: ## Summary, ## Decisions, ## Action items" beats a vague "summarize".
|
||||
3. **Be concrete about format.** If you want a checklist, say "a Markdown checklist with `- [ ]` items".
|
||||
4. **Extract, do not invent.** Tell the model to leave a section out when there is nothing for it, rather than padding.
|
||||
5. **Keep it short.** A focused prompt outperforms a long one. One template, one job.
|
||||
6. **Test and iterate.** Run it on a real transcript and adjust the wording.
|
||||
|
||||
## Keeping templates up to date
|
||||
|
||||
The Templates section has three buttons (see [Settings reference](Settings-Reference)):
|
||||
|
||||
- **Populate**: adds any missing default templates plus the shared core and guide. Never overwrites your files.
|
||||
- **Update**: reconciles your default-derived templates with the current built-ins using a per-field 3-way merge. Pristine fields (never edited, matching a current or previously shipped default) are brought forward; your edits are kept. Anything it cannot auto-merge (notably an edited prompt body that diverges from a changed default) is written to `Template update report.md` next to the templates folder for you to review. Re-serializing frontmatter drops any YAML comments you added; the prompt body is left untouched.
|
||||
- **Load prior versions**: writes earlier shipped versions of the defaults as standalone, separately-named templates so you can compare prompt wording. They never collide with your live templates.
|
||||
|
||||
## Cross-references
|
||||
|
||||
- [Providers](Providers) for diarization, context hints, and known nouns, which interact with templates.
|
||||
- [Settings reference](Settings-Reference) for the Templates, Shared core, and Known nouns settings.
|
||||
|
||||
[Back to Home](Home)
|
||||
34
wiki/Home.md
Normal file
34
wiki/Home.md
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
# ReWrite (Voice Notes) wiki
|
||||
|
||||
ReWrite is an Obsidian plugin that captures speech (live recording or a pasted transcript), runs it through a transcription provider, cleans and structures it with an LLM, and inserts the result into your vault. You bring your own provider keys; nothing is sent to a ReWrite server. It can also run entirely on-device by pairing the plugin-managed whisper.cpp transcription with a local OpenAI-compatible LLM.
|
||||
|
||||
**New here? Start with the [Quick start](Quick-Start).** It walks you from install to your first note in a few minutes.
|
||||
|
||||
## Contents
|
||||
|
||||
### Getting started
|
||||
- [Quick start](Quick-Start) - install, populate templates, and create your first note (Daily note example).
|
||||
|
||||
### Reference
|
||||
- [Settings reference](Settings-Reference) - every setting in the plugin's settings tab, section by section.
|
||||
- [Commands and menus](Commands-and-Menus) - the command palette, ribbon, editor and file menus, and Quick Record.
|
||||
- [Creating templates](Creating-Templates) - the template file format and a full guide to writing your own.
|
||||
- [Providers](Providers) - choosing and configuring transcription and LLM providers, models, diarization, context hints, and known nouns.
|
||||
|
||||
### Self-hosting
|
||||
- [Self-hosting: whisper.cpp](Self-Hosting-Whisper) - on-device transcription with the plugin-managed local whisper.cpp server.
|
||||
- [Self-hosting: local and remote LLMs](Self-Hosting-LLMs) - Ollama / llama.cpp locally or on a remote server, with model picks for low-spec hardware.
|
||||
|
||||
### Help
|
||||
- [Secrets and sync](Secrets-and-Sync) - how API keys are encrypted, and how to exclude `secrets.json.nosync` from each sync tool.
|
||||
- [Mobile](Mobile) - what behaves differently on iOS and Android.
|
||||
- [Troubleshooting](Troubleshooting) - triage for the most common problems.
|
||||
|
||||
## How it works at a glance
|
||||
|
||||
1. **Capture**: record in Obsidian, paste a transcript, or pull text from a note. You can also reprocess an audio file already in your vault.
|
||||
2. **Transcribe**: audio goes to your configured transcription provider (skipped for text input).
|
||||
3. **Clean and structure**: the transcript is sent to your LLM with the selected template's prompt, the shared-core baseline, and any known nouns or spoken instructions.
|
||||
4. **Insert**: the result lands at your cursor, appended to the current note, or in a new note, per the template. Recorded audio is saved and linked back with an `![[...]]` embed.
|
||||
|
||||
These docs are maintained in the [`wiki/` folder of the code repo](https://github.com/WiseGuru/ReWrite-Voice-Notes/tree/master/wiki) and mirrored here automatically. Edit them there, not in the wiki.
|
||||
29
wiki/Mobile.md
Normal file
29
wiki/Mobile.md
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
# Mobile
|
||||
|
||||
Obsidian on iOS and Android runs in a constrained WebView, so a few things behave differently from desktop.
|
||||
|
||||
## Screen-off during recording
|
||||
|
||||
Mobile WebViews suspend (and stop `MediaRecorder` capture) when the screen sleeps. To counter this, the plugin holds a screen wake lock for the duration of an active recording on both iOS and Android, so screen-off mid-recording is largely mitigated on supported OS versions. It is best-effort: on older WebViews, in an insecure context, or if the OS denies the request, it silently falls back, so keeping the screen on (or using the Paste tab with an OS-level dictation keyboard) is still the safe habit. The trade-off is that the screen stays lit while recording.
|
||||
|
||||
## Encryption on mobile
|
||||
|
||||
If your Obsidian version provides secret storage on mobile, keys use it just like on desktop. Otherwise the plugin prompts you to set a passphrase before any key can be saved, and keys are then encrypted with Argon2id/PBKDF2 AES-GCM. The `secrets.json.nosync` file (which holds encrypted keys only in passphrase mode) uses the `.nosync` suffix so iCloud Drive skips it; for other sync tools, see [Secrets and sync](Secrets-and-Sync).
|
||||
|
||||
## Recording size limits
|
||||
|
||||
Each transcription provider enforces its own ceiling. OpenAI Whisper and Groq are the tightest at 25 MB; AssemblyAI, Deepgram, and Rev.ai allow gigabytes. These are provider-API limits, not Obsidian ones, and are most likely to bite on long mobile recordings with the 25 MB providers. See per-provider limits in [Providers](Providers).
|
||||
|
||||
## Local whisper.cpp is desktop only
|
||||
|
||||
The plugin-managed local whisper.cpp server spawns a native child process and is unavailable on mobile. The option is hidden from the mobile profile's provider dropdown. Use a cloud transcription provider, or a remote OpenAI-compatible transcription server, on mobile.
|
||||
|
||||
## Keyboard and layout
|
||||
|
||||
The plugin pins its popups to the top of the screen on mobile so they stay visible above the soft keyboard, and trims a few input sizes (for example the Paste box renders shorter) so submit buttons stay reachable. No configuration needed.
|
||||
|
||||
## Profiles
|
||||
|
||||
The plugin ships separate Desktop and Mobile profiles so you can, for example, use a local stack on desktop and cloud providers on your phone. Each device auto-detects its profile; you can override which is active in Settings, Active profile. See [Settings reference](Settings-Reference).
|
||||
|
||||
[Back to Home](Home)
|
||||
99
wiki/Providers.md
Normal file
99
wiki/Providers.md
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
# Providers
|
||||
|
||||
ReWrite separates transcription (audio to text) from cleanup (text to structured note). Each profile has one transcription slot and one LLM slot, with their own keys. This page covers choosing and configuring providers, models, diarization, context hints, and known nouns.
|
||||
|
||||
For fully local setups, see [Self-hosting: whisper.cpp](Self-Hosting-Whisper) and [Self-hosting: local and remote LLMs](Self-Hosting-LLMs).
|
||||
|
||||
## Transcription providers
|
||||
|
||||
| Provider | API key | Model dropdown | Diarization | Notes |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| OpenAI Whisper (`openai`) | Yes | Yes | No | 25 MB upload cap. |
|
||||
| OpenAI-compatible (`openai-compatible`) | Yes | No (type the id) | No | For self-hosted Whisper-shape servers; see base URL below. |
|
||||
| Groq (`groq`) | Yes | Yes | No | 25 MB upload cap. |
|
||||
| AssemblyAI (`assemblyai`) | Yes | No (docs link) | Yes | Large ceiling (5 GB / 10 h). |
|
||||
| Deepgram (`deepgram`) | Yes | No (docs link) | Yes | 2 GB cap. |
|
||||
| Rev.ai (`revai`) | Yes | No (docs link) | Yes | 2 GB / 17 h. |
|
||||
| Mistral Voxtral (`mistral-voxtral`) | Yes | Yes (filtered) | No | Always transcodes to WAV; 30-minute cap. |
|
||||
| Local whisper.cpp (`whisper-local`) | No | No | No | Desktop only, on-device. See [whisper.cpp](Self-Hosting-Whisper). |
|
||||
| None (`none`) | n/a | n/a | n/a | Disables recording for text-only use. |
|
||||
|
||||
## LLM providers
|
||||
|
||||
| Provider | API key | Model dropdown | Notes |
|
||||
| --- | --- | --- | --- |
|
||||
| Anthropic Claude (`anthropic`) | Yes | Yes | Calls go through Obsidian's `requestUrl` (no browser CORS). |
|
||||
| OpenAI GPT (`openai`) | Yes | Yes | Reasoning models (o-series, gpt-5) handled automatically. |
|
||||
| OpenAI-compatible (`openai-compatible`) | Yes | No (type the id) | Cloud or local; base URL must include the version path. |
|
||||
| Google Gemini (`gemini`) | Yes | Yes | Silently clamps overlong output rather than erroring. |
|
||||
| Mistral (`mistral`) | Yes | Yes | |
|
||||
| None (`none`) | n/a | n/a | Skips cleanup; inserts the raw transcript. |
|
||||
|
||||
## API keys
|
||||
|
||||
Keys are stored per profile (one transcription, one LLM), encrypted at rest. The desktop and mobile profiles keep their own keys even when both use the same provider. See [Secrets and sync](Secrets-and-Sync).
|
||||
|
||||
## Choosing a model
|
||||
|
||||
The model field adapts to the provider:
|
||||
|
||||
- **Providers that support listing models** (OpenAI, Groq, Anthropic, Gemini, Mistral, Deepgram, Mistral Voxtral) show a **dropdown** once you click **Refresh** to fetch the catalog your key can access. The dropdown has a **"Custom..."** option to type an id that is not in the list, and a "Back to list" button to return.
|
||||
- **Providers without listing** (`openai-compatible`, AssemblyAI, Rev.ai) show a **plain text field**. For AssemblyAI and Rev.ai the field links to the provider's model docs; for `openai-compatible` there is no list because the catalog is your own server's.
|
||||
|
||||
Whatever the control, the value saved is the model id sent to the provider.
|
||||
|
||||
## Maximum note length (output cap)
|
||||
|
||||
"Maximum note length" frames the LLM's output-token cap in minutes of speech. If the cap is set higher than a model's own output ceiling, OpenAI and Anthropic return a friendly error pointing back at this setting; Gemini silently truncates instead. The Advanced "LLM max tokens" field edits the same value raw.
|
||||
|
||||
## OpenAI-compatible base URLs
|
||||
|
||||
There is an intentional asymmetry between the two sides; do not normalize one to the other:
|
||||
|
||||
- **Transcription** appends `/v1/audio/transcriptions` to a **root** URL. Enter `http://localhost:8080` (no `/v1`).
|
||||
- **LLM** appends `/chat/completions` to a URL that **already includes** `/v1`. Enter `http://localhost:11434/v1` (with `/v1`).
|
||||
|
||||
This is why a local Ollama LLM uses `http://localhost:11434/v1` while a local Whisper-shape transcription server uses its root URL. See [Self-hosting: local and remote LLMs](Self-Hosting-LLMs) for Ollama specifics.
|
||||
|
||||
### Cloud OpenAI-compatible LLMs
|
||||
|
||||
Many cloud LLM services speak the same `/chat/completions` dialect, so they work through the **OpenAI-compatible** LLM provider with no first-class entry. Set the provider, paste a base URL (including its version path), type a model id, and enter your key.
|
||||
|
||||
| Provider | LLM base URL | Example models |
|
||||
| --- | --- | --- |
|
||||
| DeepSeek | `https://api.deepseek.com/v1` | `deepseek-chat`, `deepseek-reasoner` |
|
||||
| Kimi (Moonshot) | `https://api.moonshot.ai/v1` | `kimi-k2-0905-preview`, `moonshot-v1-32k` |
|
||||
| Qwen (DashScope) | `https://dashscope-intl.aliyuncs.com/compatible-mode/v1` | `qwen-max`, `qwen-plus` |
|
||||
| Zhipu GLM | `https://open.bigmodel.cn/api/paas/v4` | `glm-4-plus` |
|
||||
|
||||
The URLs above are international endpoints; China-region accounts can substitute mainland endpoints (for example `https://api.moonshot.cn/v1`, `https://dashscope.aliyuncs.com/compatible-mode/v1`).
|
||||
|
||||
## Speaker diarization
|
||||
|
||||
Diarization adds `Speaker A:` / `Speaker B:` labels and is supported only on **AssemblyAI**, **Deepgram**, and **Rev.ai**. Two switches raise the effective setting:
|
||||
|
||||
- The per-profile **Identify speakers** toggle (Settings).
|
||||
- A per-template `diarize: true` flag (the Meeting transcript default ships with it). The flag only ever raises the setting; it is a documented no-op on providers that cannot diarize.
|
||||
|
||||
The labels survive cleanup because the shared core instructs the LLM to preserve them.
|
||||
|
||||
## Context hint
|
||||
|
||||
A per-run free-text field for one-off background (speakers, setting, subject), for example "Lecture by Dr. Smith on thermodynamics". It is the situational counterpart to the persistent known-nouns list and pairs naturally with diarization (mapping `Speaker X:` labels to real names). It is shown only for templates with `enableContextHint: true`, in the main modal and the reprocess picker. The cleanup step treats it as reference, not instructions.
|
||||
|
||||
## Known nouns
|
||||
|
||||
`ReWrite/KnownNouns.md` lists proper nouns the LLM should preserve verbatim, one per line, with optional misheard variants (`Hoxhunt: hawks hunt, hocks hunt`). When non-empty, the list is injected into the cleanup prompt. The file's frontmatter is human guidance only and is never sent to the LLM. Keep the list short; every entry costs tokens on every run.
|
||||
|
||||
## Per-provider recording limits
|
||||
|
||||
The plugin validates a recording against the provider's documented ceiling before sending, with a friendly error if it is too large:
|
||||
|
||||
- `openai` / `groq`: 25 MB
|
||||
- `assemblyai`: 5 GB / 10 h
|
||||
- `deepgram`: 2 GB
|
||||
- `revai`: 2 GB / 17 h
|
||||
- `mistral-voxtral`: 1 GB / 30 min
|
||||
- `openai-compatible` / `whisper-local`: no client-side cap
|
||||
|
||||
[Back to Home](Home)
|
||||
70
wiki/Quick-Start.md
Normal file
70
wiki/Quick-Start.md
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
# Quick start
|
||||
|
||||
This page takes you from a fresh install to your first cleaned-up note. It uses the **Daily note** template as the worked example, but the same flow applies to every template.
|
||||
|
||||
For deeper detail on any step, see [Settings reference](Settings-Reference), [Providers](Providers), and [Creating templates](Creating-Templates).
|
||||
|
||||
## 1. Install the plugin
|
||||
|
||||
### Community plugins (recommended)
|
||||
|
||||
1. In Obsidian, open Settings, Community plugins, and turn off Restricted mode if it is on.
|
||||
2. Click Browse, search for "ReWrite (Voice Notes)", and click Install, then Enable.
|
||||
|
||||
### Manual install (latest release)
|
||||
|
||||
If the plugin is not yet listed, or you want a specific build:
|
||||
|
||||
1. Download `main.js`, `manifest.json`, and `styles.css` from the latest entry on the [Releases page](https://github.com/WiseGuru/ReWrite-Voice-Notes/releases).
|
||||
2. Create the folder `<YourVault>/.obsidian/plugins/rewrite-voice-notes/`.
|
||||
3. Copy the three files into that folder.
|
||||
4. In Obsidian, open Settings, Community plugins, and enable "ReWrite (Voice Notes)" (Restricted mode off).
|
||||
|
||||
## 2. Configure a provider
|
||||
|
||||
Open Settings, ReWrite (Voice Notes). The plugin has two profiles (one for desktop, one for mobile) so you can use different providers on each device. Configure the profile marked active on this device:
|
||||
|
||||
- **Transcription provider** (turns audio into text): pick a provider, enter its API key, and choose a model. Skip this if you only ever paste or process existing text.
|
||||
- **LLM provider** (cleans and structures the text): pick a provider, enter its API key, and choose a model.
|
||||
|
||||
You bring your own keys; nothing is sent to a ReWrite server. The first time you save a key, the plugin sets up encryption at rest (your OS secret store, or a passphrase you choose). See [Providers](Providers) for the full provider list and [Secrets and sync](Secrets-and-Sync) for how keys are stored.
|
||||
|
||||
Want zero cloud dependency? See [Self-hosting: whisper.cpp](Self-Hosting-Whisper) and [Self-hosting: local and remote LLMs](Self-Hosting-LLMs).
|
||||
|
||||
## 3. Install the templates
|
||||
|
||||
ReWrite keeps its templates as Markdown files in your vault, not buried in settings. They do not exist until you create them:
|
||||
|
||||
1. In Settings, scroll to the **Templates** section.
|
||||
2. Click **Populate**.
|
||||
|
||||
This creates, under `ReWrite/` in your vault:
|
||||
|
||||
- `ReWrite/Templates/` with 10 starter templates (General cleanup, Todo list, Daily note, Meeting notes, Meeting transcript, Idea capture, Lecture, Podcast, Guides, Book log).
|
||||
- `ReWrite/SharedCore.md`, the cleanup ground rules prepended to every template.
|
||||
- `ReWrite/AssistantPrompt.md` and `ReWrite/KnownNouns.md`, optional helpers.
|
||||
- `ReWrite/Template guide.md`, a human-facing explanation of the format (never sent to an LLM).
|
||||
|
||||
Populate is non-destructive: re-running it only adds what is missing, so your edits are safe. To pull in changed defaults later, use **Update** instead (see [Creating templates](Creating-Templates)).
|
||||
|
||||
## 4. Create your first note (Daily note)
|
||||
|
||||
The **Daily note** template writes a new, date-named note: it pulls out Calendar, Goals, and Tasks sections when you mention them, then drops the full cleaned transcript into a Braindump section.
|
||||
|
||||
1. Click the **mic ribbon icon** (or run the **Open** command from the command palette).
|
||||
2. In the template dropdown at the top, choose **Daily note**.
|
||||
3. Either:
|
||||
- **Record**: click Record, speak (for example: "Today I have a dentist appointment at 2pm. My goal is to finish the quarterly report. I need to email Sarah and buy groceries. Also I keep thinking about that side project idea..."), then Stop. The original audio is saved to your attachments folder and linked into the note.
|
||||
- **Paste**: switch to the Paste tab and paste an existing transcript instead. No transcription provider needed for this path.
|
||||
4. The plugin transcribes (if recording), cleans the text with your LLM, and creates a new dated note with the structured result.
|
||||
|
||||
That's the whole loop: capture, clean, insert. Swap the template to change the shape of the output.
|
||||
|
||||
## 5. Where to go next
|
||||
|
||||
- **Faster capture**: [Quick Record](Commands-and-Menus) records with no modal, using your last or a pinned template. Press the hotkey once to start, again to stop.
|
||||
- **Process existing text or audio**: run a template over a selection, or reprocess an audio file already in your vault. See [Commands and menus](Commands-and-Menus).
|
||||
- **Make it yours**: edit the bundled templates or write new ones in [Creating templates](Creating-Templates).
|
||||
- **Run it locally**: [whisper.cpp](Self-Hosting-Whisper) for on-device transcription, [local LLMs](Self-Hosting-LLMs) for on-device cleanup.
|
||||
|
||||
[Back to Home](Home)
|
||||
94
wiki/Secrets-and-Sync.md
Normal file
94
wiki/Secrets-and-Sync.md
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
# Secrets and sync
|
||||
|
||||
How ReWrite stores your API keys, and how to keep the key file off whatever sync mechanism you use.
|
||||
|
||||
## Where keys live
|
||||
|
||||
API keys are stored in `<YourVault>/.obsidian/plugins/rewrite-voice-notes/secrets.json.nosync`, separately from the rest of the plugin's settings (`data.json`). Keys are never written to `data.json`.
|
||||
|
||||
## Encryption modes
|
||||
|
||||
The plugin encrypts keys at rest in one of two modes, selectable in Settings under **API key encryption**. There is no unencrypted option.
|
||||
|
||||
- **Obsidian secret storage** (`secretStorage`): the default when available (a recent Obsidian with a working OS secret store). Keys go into Obsidian's built-in secret store, encrypted at rest by your OS keychain and shared across plugins. Because it is Obsidian-managed, **if you use Obsidian Sync these keys may sync across your devices**, a convenience that also means your keys leave the single-device boundary. The plugin runs a round-trip self-test and falls back to passphrase on a device without a working OS secret store (for example Linux without a keyring). In this mode the keys do **not** live in `secrets.json.nosync` (that file only records which mode is in use).
|
||||
- **Passphrase**: AES-GCM with a key derived from a passphrase you set, using Argon2id (memory-hard) or PBKDF2 where Argon2id cannot run. Works on every platform including mobile; the keys stay on the device (encrypted in `secrets.json.nosync`) and the blob is portable (re-enter the passphrase to unlock on each device). The plugin enforces a minimum passphrase strength and offers a one-click 6-word generator. On devices where secret storage is unavailable, setting a passphrase is required before any key can be saved.
|
||||
|
||||
Passphrase mode locks and unlocks: **Lock now** clears the derived key from memory, and the next pipeline run prompts you to unlock. The derived key never touches disk.
|
||||
|
||||
The deeper implementation detail (envelope schema, KDF parameters, migration) is developer-facing and lives in the repo's `docs/SECRETS.md`.
|
||||
|
||||
## Excluding `secrets.json.nosync` from sync
|
||||
|
||||
If you use **passphrase mode** and do not want the encrypted key file copied between devices, exclude it from your sync and enter keys once per device. Configure the exclusion **before the first sync**, since files already uploaded usually remain on the remote. (In secret-storage mode this file holds no keys, so excluding it has no effect on the keys themselves.)
|
||||
|
||||
The path to exclude is always:
|
||||
|
||||
```
|
||||
.obsidian/plugins/rewrite-voice-notes/secrets.json.nosync
|
||||
```
|
||||
|
||||
### Obsidian Sync (official)
|
||||
|
||||
Obsidian Sync excludes folders, not individual files (Settings, Sync, Excluded folders). Two options:
|
||||
|
||||
- Exclude the whole `.obsidian/plugins/rewrite-voice-notes` folder and accept losing template/profile sync (`data.json` lives there too).
|
||||
- Or sync the folder and accept that the encrypted `secrets.json.nosync` blob uploads; on other devices it fails to decrypt and the plugin treats it as no key set, prompting you to re-enter.
|
||||
|
||||
### Syncthing
|
||||
|
||||
Add to `.stignore` in the synced folder root:
|
||||
|
||||
```
|
||||
// ReWrite plugin secrets, never sync API keys
|
||||
.obsidian/plugins/rewrite-voice-notes/secrets.json.nosync
|
||||
```
|
||||
|
||||
If the vault is not at the Syncthing folder root, omit the leading slash from any patterns.
|
||||
|
||||
### Resilio Sync
|
||||
|
||||
Add this line to `.sync/IgnoreList` on each peer:
|
||||
|
||||
```
|
||||
.obsidian/plugins/rewrite-voice-notes/secrets.json.nosync
|
||||
```
|
||||
|
||||
### Git / GitHub
|
||||
|
||||
Add to the vault's `.gitignore`:
|
||||
|
||||
```gitignore
|
||||
# ReWrite plugin, never commit API keys
|
||||
.obsidian/plugins/rewrite-voice-notes/secrets.json.nosync
|
||||
```
|
||||
|
||||
If you already committed it:
|
||||
|
||||
```bash
|
||||
git rm --cached .obsidian/plugins/rewrite-voice-notes/secrets.json.nosync
|
||||
git commit -m "remove rewrite-voice-notes secrets from tracking"
|
||||
```
|
||||
|
||||
### Dropbox
|
||||
|
||||
Dropbox has no ignore-file mechanism. Use Selective Sync:
|
||||
|
||||
1. Open the Dropbox desktop app.
|
||||
2. Preferences, Sync, Selective Sync.
|
||||
3. Deselect the `rewrite-voice-notes` plugin folder, or use file-level exclusions if your plan supports them.
|
||||
|
||||
Alternatively, delete `secrets.json.nosync` from Dropbox via the web interface after setup; the plugin recreates it locally when you next enter keys.
|
||||
|
||||
### iCloud Drive
|
||||
|
||||
No configuration needed. iCloud Drive automatically skips any file whose name ends in `.nosync`, which is why the plugin uses that suffix.
|
||||
|
||||
### FolderSync (Android)
|
||||
|
||||
In each sync pair, go to Filters, Excluded files, and add the pattern:
|
||||
|
||||
```
|
||||
secrets.json.nosync
|
||||
```
|
||||
|
||||
[Back to Home](Home)
|
||||
70
wiki/Self-Hosting-LLMs.md
Normal file
70
wiki/Self-Hosting-LLMs.md
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
# Self-hosting: local and remote LLMs
|
||||
|
||||
ReWrite's cleanup step works with any server that speaks the OpenAI `/chat/completions` dialect, through the **OpenAI-compatible** LLM provider. That covers Ollama, llama.cpp's `llama-server`, LM Studio, and most self-hosted gateways, whether on your own machine or a remote box.
|
||||
|
||||
Pair this with [local whisper.cpp](Self-Hosting-Whisper) so neither audio nor text leaves your machine.
|
||||
|
||||
## Running locally (Ollama)
|
||||
|
||||
[Ollama](https://ollama.com) is the easiest starting point on macOS, Linux, and Windows.
|
||||
|
||||
1. Install Ollama and start it (`ollama serve`, or it runs as a service).
|
||||
2. Pull a model: `ollama pull llama3.2` (see the model picks below).
|
||||
3. In a ReWrite profile, set **LLM provider** to "OpenAI-compatible (cloud or local)".
|
||||
4. **LLM base URL**: `http://localhost:11434/v1`
|
||||
5. **LLM model**: the pulled name, for example `llama3.2`.
|
||||
6. **API key**: Ollama ignores it, so any non-empty placeholder works.
|
||||
|
||||
Note the `/v1`: for the LLM side the base URL **must include the version path**, because the adapter appends `/chat/completions` to whatever you enter. (The transcription side is different; see the base-URL asymmetry in [Providers](Providers).)
|
||||
|
||||
### llama.cpp
|
||||
|
||||
Run `llama-server -m <model.gguf>`. Base URL `http://localhost:8080/v1`, model = whatever name the server reports.
|
||||
|
||||
## Running on a remote / self-hosted server
|
||||
|
||||
The setup is the same; you just point the base URL at the remote host. The important part is **not** exposing the raw model port to the internet. Ollama's API has no authentication, so a public `11434` lets anyone use (and abuse) your GPU.
|
||||
|
||||
Recommended approaches, safest first:
|
||||
|
||||
1. **Private tunnel (best).** Keep the server bound to localhost and reach it over WireGuard, Tailscale, or an SSH tunnel (`ssh -L 11434:localhost:11434 user@host`). Then use `http://localhost:11434/v1` as if it were local. No public port at all.
|
||||
2. **Reverse proxy with TLS and auth.** Put nginx or Caddy in front, terminate HTTPS, and require a token (bearer header) or basic auth. Bind Ollama to localhost and let only the proxy talk to it. Then the base URL is `https://your-host/v1` and you put the token in the API key field (for bearer) or in the URL/proxy config.
|
||||
3. **Bind Ollama to the LAN only** (`OLLAMA_HOST=0.0.0.0:11434`) behind a firewall, for a trusted home network. Acceptable on an isolated LAN; never do this on a public IP without a proxy in front.
|
||||
|
||||
Do not expose Ollama's port directly to the public internet.
|
||||
|
||||
## Hardware and model picks
|
||||
|
||||
Running a model locally is more demanding than calling a cloud API: you need enough RAM (and ideally a GPU) to hold the model. The good news is that ReWrite's job (cleaning and lightly structuring a transcript) is undemanding, so small instruct-tuned models do it well. You do not need a 70B model to fix grammar and add headings.
|
||||
|
||||
Use 4-bit quantization (Ollama's default `Q4_K_M`) as a starting point and move to `Q5_K_M` only if quality falls short. RAM figures below are rough 4-bit estimates; a GPU with that much VRAM is faster, but CPU + system RAM works for short notes.
|
||||
|
||||
| Model | Params | ~RAM (4-bit) | Pull | Good for |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| Llama 3.2 1B | 1B | ~2-3 GB | `ollama pull llama3.2:1b` | Lightest option; fine for cleanup on low-end laptops. |
|
||||
| SmolLM2 1.7B | 1.7B | ~4 GB | `ollama pull smollm2:1.7b` | Fast, tiny, good for short notes. |
|
||||
| Phi-4-mini | 3.8B | ~3-4 GB | `ollama pull phi4-mini` | Strong instruction-following in a small footprint; long context. |
|
||||
| Llama 3.2 3B | 3B | ~6 GB | `ollama pull llama3.2` | A solid all-rounder; good default if unsure. |
|
||||
| Gemma 3 4B | 4B | ~6 GB | `ollama pull gemma3:4b` | Good instruction-following from Google. |
|
||||
| Qwen3 4B | 4B | ~6 GB | `ollama pull qwen3:4b` | Capable small model; strong at structure. |
|
||||
| Qwen3 8B | 8B | ~8-10 GB | `ollama pull qwen3:8b` | Step up when you have the headroom. |
|
||||
| Ministral 8B | 8B | ~10 GB | `ollama pull mistral:8b` | Competitive with larger models; needs more RAM. |
|
||||
|
||||
These are guidance, not gospel; model availability and tags move quickly, so check the [Ollama library](https://ollama.com/library) for current names. If a model feels too terse or ignores your template structure, step up a size or try `Q5_K_M`. (This list refreshes the older [MachineLearningMastery "Top 7"](https://machinelearningmastery.com/top-7-small-language-models-you-can-run-on-a-laptop/) roundup, which still cited Phi-3.5, Llama 3.2, Qwen 2.5, and Gemma 2.)
|
||||
|
||||
For a rule of thumb: 8 GB RAM comfortably runs a 3B-4B model; 16 GB opens up 7B-8B; below 8 GB, stick to 1B-2B.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
- **Connection refused / network error**: Ollama (or your server) is not running, or the host/port is wrong. Confirm `ollama serve` is up and that `http://localhost:11434/v1/models` responds in a browser or `curl`.
|
||||
- **404 Not Found**: almost always the `/v1` path. The LLM base URL must end in `/v1` (Ollama) or the right version path; the adapter adds `/chat/completions`. A doubled `/v1/v1` also 404s.
|
||||
- **Model not found**: the model id does not match a pulled model. Run `ollama list` and use the exact name (including the tag, for example `llama3.2:1b`).
|
||||
- **Works locally but not from another device**: Ollama binds to localhost by default. Set `OLLAMA_HOST=0.0.0.0:11434` to listen on the LAN (behind a firewall), or use a tunnel/proxy as above.
|
||||
- **CORS errors**: ReWrite calls go through Obsidian's `requestUrl`, which bypasses browser CORS, so this is rare. If a proxy enforces origins, set `OLLAMA_ORIGINS` appropriately on the server.
|
||||
- **Very slow first response**: the model is loading into memory on the first call. Subsequent calls are faster while it stays resident.
|
||||
- **Output cut off / truncated**: lower the "Maximum note length" if your model has a small output limit, or pick a model with a larger context. Some local models silently truncate rather than erroring.
|
||||
- **Garbled or off-task output**: the model is too small for the template's structure. Step up a size, or simplify the template prompt.
|
||||
|
||||
See also the general [Troubleshooting](Troubleshooting) page and [Providers](Providers) for the base-URL conventions.
|
||||
|
||||
[Back to Home](Home)
|
||||
102
wiki/Self-Hosting-Whisper.md
Normal file
102
wiki/Self-Hosting-Whisper.md
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
# Self-hosting: whisper.cpp
|
||||
|
||||
For fully on-device transcription with no network calls, ReWrite can spawn a [whisper.cpp](https://github.com/ggerganov/whisper.cpp) `whisper-server` binary that you supply. The plugin only reads the absolute paths you configure; it never downloads binaries, never looks them up on PATH, and never spawns anything you did not explicitly point it at. **Desktop only.**
|
||||
|
||||
Pair this with a [local LLM](Self-Hosting-LLMs) for a setup where neither audio nor text leaves your machine.
|
||||
|
||||
## How it works and the security model
|
||||
|
||||
When you click Start in settings, the plugin launches whisper-server as a child process and talks to it over loopback (`http://127.0.0.1:<port>/inference`). Its stdout/stderr are captured in a ring-buffered log you can view in settings. When you click Stop, or when the plugin unloads, the process is terminated. The plugin records a small PID sidecar file so that if Obsidian restarts while the server is still running, it can re-adopt that exact process instead of orphaning or double-spawning it. It will never kill a process it did not start.
|
||||
|
||||
**Loopback only.** whisper-server has no authentication and no TLS, so anyone who can reach its port can submit audio and exercise its native audio-decoding code. ReWrite always passes `--host 127.0.0.1` when you do not specify a host, and **refuses to start** if you put a non-loopback `--host` (such as `0.0.0.0` or a LAN IP) in Extra args. The exact refusal is:
|
||||
|
||||
> Refusing to start: --host <value> would bind whisper-server to a non-loopback interface, exposing an unauthenticated transcription server to your network. Remove it from Extra args; ReWrite always binds 127.0.0.1.
|
||||
|
||||
Loopback values it accepts: `127.0.0.1`, `localhost`, `::1`, `[::1]`. If you run whisper-server yourself from a terminal, bind it to `127.0.0.1` the same way; do not expose it to your network unless you have put your own authenticating proxy in front of it.
|
||||
|
||||
## Setup
|
||||
|
||||
### 1. Get a `whisper-server` binary
|
||||
|
||||
- **Windows**: download the latest `whisper-bin-x64.zip` (CPU) or `whisper-cublas-*.zip` (NVIDIA GPU) from the [whisper.cpp releases page](https://github.com/ggerganov/whisper.cpp/releases), unzip somewhere stable (for example `C:\Tools\whisper.cpp\`), and use the path to `whisper-server.exe`.
|
||||
- **macOS**: `brew install whisper-cpp` installs a `whisper-server` binary; `which whisper-server` shows its absolute path. Or build from source as on Linux.
|
||||
- **Linux**: there are no official Linux binaries, so build from source once (see below).
|
||||
|
||||
### 2. Download a GGML model
|
||||
|
||||
- **Upstream GGML models** from [Hugging Face](https://huggingface.co/ggerganov/whisper.cpp/tree/main), for example `ggml-base.en.bin`, `ggml-small.bin`, `ggml-large-v3.bin`. Larger is more accurate and slower.
|
||||
- **FUTO whisper-acft models** (see below): quantized, finetuned variants that support a dynamic audio context for lower latency. They load with the same `-m` flag.
|
||||
|
||||
### 3. Configure the plugin
|
||||
|
||||
In ReWrite settings, scroll to **Local whisper.cpp server (desktop)** and fill in:
|
||||
|
||||
- **Binary path**: absolute path to `whisper-server` (or `whisper-server.exe`). The **Auto-detect** button checks common install locations (`~/.local/bin`, `~/.local/share/whisper.cpp/build/bin`, `/usr/local/bin`, `/opt/homebrew/bin`, `/usr/bin`) and fills the field if it finds one.
|
||||
- **Model path**: absolute path to the `.bin` model file.
|
||||
- **Port**: defaults to 8080.
|
||||
- **Extra args** (optional): space-separated CLI args appended after `-m` and `--port`. Split on whitespace only (a single value containing spaces, such as a quoted path, is not supported). Do not add a non-loopback `--host` here.
|
||||
|
||||
### 4. Start it
|
||||
|
||||
Click **Start**. The status indicator moves Stopped, Starting, Running. **View log** shows whisper-server's output if startup fails. You can also start/stop from the command palette and the desktop status-bar item.
|
||||
|
||||
### 5. Use it from a profile
|
||||
|
||||
Set the profile's **Transcription provider** to "Local whisper.cpp (desktop only)". The Transcription model field is decorative for this provider; whisper-server uses whichever model file is loaded at startup. No API key is needed. The plugin transcodes recordings to 16 kHz mono WAV before sending them to `/inference`.
|
||||
|
||||
## Building whisper-server on Linux
|
||||
|
||||
whisper.cpp does not publish prebuilt Linux binaries, so compile it once. There is a helper script in the repo at `scripts/build-whisper-linux.sh`, or do it by hand:
|
||||
|
||||
1. Install the toolchain for your distro:
|
||||
- Debian / Ubuntu / Mint: `sudo apt update && sudo apt install -y build-essential cmake git`
|
||||
- Fedora / RHEL: `sudo dnf install -y gcc-c++ make cmake git`
|
||||
- Arch / Manjaro: `sudo pacman -S --needed base-devel cmake git`
|
||||
- openSUSE: `sudo zypper install -y gcc-c++ make cmake git`
|
||||
2. Clone and build:
|
||||
```bash
|
||||
git clone https://github.com/ggerganov/whisper.cpp.git
|
||||
cd whisper.cpp
|
||||
cmake -B build -DCMAKE_BUILD_TYPE=Release
|
||||
cmake --build build -j --config Release
|
||||
```
|
||||
The default build includes the `server` example. For CUDA, add `-DGGML_CUDA=ON` to the first `cmake` line (requires the CUDA toolkit; longer build).
|
||||
3. The binary lands at `<clone>/build/bin/whisper-server`. Copy or symlink it somewhere stable (for example `~/.local/bin/whisper-server`) and ensure it is executable (`chmod +x`).
|
||||
4. Sanity-check it once from a terminal: `./build/bin/whisper-server -m /path/to/model.bin --host 127.0.0.1 --port 8080`. You should see `whisper server listening at http://127.0.0.1:8080`. Ctrl-C to stop, then let the plugin manage it.
|
||||
|
||||
If `cmake --build` fails with `'std::filesystem' has not been declared` or similar C++17 errors, your GCC is too old. Install a newer one (`sudo apt install g++-12`) and rerun the `cmake -B build ...` step with `-DCMAKE_CXX_COMPILER=g++-12`.
|
||||
|
||||
## FUTO whisper-acft models (faster short clips)
|
||||
|
||||
[whisper-acft](https://github.com/futo-org/whisper-acft) is a set of Whisper checkpoints finetuned by FUTO so whisper.cpp's encoder tolerates a dynamic `audio_ctx` (the number of audio frames it processes). Lowering the audio context on a stock model makes it unstable; the ACFT models were retrained to handle it, cutting latency on short utterances (often a 2x to 4x speedup on small models).
|
||||
|
||||
The checkpoints are quantized to `q8_0` in the same GGML container the `-m` flag accepts, so no special build is needed, only a whisper.cpp recent enough to recognize the `-ac` / `--audio-context` flag.
|
||||
|
||||
1. Download a `.bin` (English-only is smaller and faster for English; multilingual handles other languages):
|
||||
- English-only: `tiny_en_acft_q8_0.bin`, `base_en_acft_q8_0.bin`, `small_en_acft_q8_0.bin`
|
||||
- Multilingual: `tiny_acft_q8_0.bin`, `base_acft_q8_0.bin`, `small_acft_q8_0.bin`
|
||||
|
||||
These are published under `https://voiceinput.futo.org/VoiceInput/`. Verify the download finished cleanly; a truncated `.bin` fails to load with a cryptic log error.
|
||||
2. Set **Model path** to the FUTO `.bin`. Binary path and Port are unchanged.
|
||||
3. Set **Extra args** to `-ac 768` (a sensible default for short to medium clips). `-ac` caps the encoder context: lower runs faster but only stays accurate on ACFT models.
|
||||
- `-ac 512` for very short memos (under ~10 s).
|
||||
- `-ac 1500` disables the speedup (the default for 30 s of audio); use it if you dictate longer than ~20 s and the tail gets cut.
|
||||
- Combine flags on one line, for example `-ac 768 -t 4` to also cap CPU threads.
|
||||
4. Click Start (or Restart). The log should show the ACFT model loading. The transcription provider needs no changes.
|
||||
|
||||
If transcripts get truncated or jumbled, `-ac` is too low for your clip length; raise it toward 1500 until stable.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
- **Port already in use**: another process is bound to the port. Change the port or stop the other process. The plugin will not kill processes it did not start.
|
||||
- **"Port N is bound by an external whisper-server"**: a whisper-server the plugin did not start holds the port. Stop it via your OS tools first.
|
||||
- **"This whisper-server was not started by ReWrite"**: you tried to Stop an externally-started server. Stop it from your task manager.
|
||||
- **Antivirus quarantine on Windows**: Defender or third-party AV may flag `whisper-server.exe` on first run. Whitelist the binary; the plugin cannot work around AV.
|
||||
- **Permission denied (macOS / Linux)**: make the binary executable (`chmod +x whisper-server`).
|
||||
- **"did not become ready within 5s"**: the model failed to load (wrong path, corrupted file, RAM exhausted). The log tail shows whisper.cpp's error.
|
||||
- **`unknown argument: -ac`**: your whisper-server predates the dynamic audio-context flag. Update whisper.cpp, or remove `-ac` (FUTO models still load, you just lose the speedup).
|
||||
- **FUTO model loads but transcripts are truncated**: `-ac` is too low for your audio length; raise it (`768` to `1024` to `1500`).
|
||||
|
||||
See also the general [Troubleshooting](Troubleshooting) page.
|
||||
|
||||
[Back to Home](Home)
|
||||
84
wiki/Settings-Reference.md
Normal file
84
wiki/Settings-Reference.md
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
# Settings reference
|
||||
|
||||
This page walks through every section of the plugin's settings tab (Settings, ReWrite (Voice Notes)), top to bottom. For provider-specific guidance see [Providers](Providers); for the local whisper server see [Self-hosting: whisper.cpp](Self-Hosting-Whisper).
|
||||
|
||||
## API key encryption
|
||||
|
||||
Controls how your provider API keys are encrypted at rest. There is no unencrypted option.
|
||||
|
||||
- **Encryption mode**: choose between **Obsidian secret storage** (the default when your Obsidian version and OS support it; keys live in the OS keychain) and **Passphrase** (AES-GCM with a key derived from a passphrase via Argon2id, or PBKDF2 where Argon2id is unavailable). A status badge next to the section heading shows the active mode and whether it is currently unlocked.
|
||||
- **Change passphrase**: set or rotate the passphrase (passphrase mode only). The plugin enforces a minimum strength and offers a one-click 6-word generator.
|
||||
- **Lock now**: clears the derived key from memory (passphrase mode). The next pipeline run prompts you to unlock.
|
||||
|
||||
Full detail, including which file holds what and how to keep keys off your sync, is on [Secrets and sync](Secrets-and-Sync).
|
||||
|
||||
## Active profile
|
||||
|
||||
- **Profile selection**: pick which profile is active. The plugin ships two profiles, **Desktop** and **Mobile**, so a device can use different providers and keys. Each device auto-detects which profile applies; this setting lets you override that.
|
||||
|
||||
## Profiles (Desktop and Mobile)
|
||||
|
||||
Each profile is rendered in its own framed section, with the device's active profile highlighted. The fields:
|
||||
|
||||
- **Profile label**: a friendly name for the profile.
|
||||
- **Transcription provider**: the service that turns audio into text. Choosing a provider reveals the fields it needs. `None` disables the recording paths for this profile (text-only use). See [Providers](Providers) for the full list.
|
||||
- **Transcription base URL**: shown only for providers that need it (for example `openai-compatible`). See [Providers](Providers) for the base-URL conventions.
|
||||
- **Transcription API key**: stored encrypted (see API key encryption above). Not shown for providers that need no key (such as local whisper.cpp).
|
||||
- **Identify speakers**: turns on diarization (`Speaker A:` / `Speaker B:` labels) when the provider supports it (AssemblyAI, Deepgram, Rev.ai). A no-op on other providers. A template can also force this on. See [Providers](Providers).
|
||||
- **LLM provider**: the model that cleans and structures the transcript. `None` skips cleanup and inserts the raw text.
|
||||
- **LLM base URL**: shown for `openai-compatible`. Note the base-URL asymmetry between transcription and LLM described in [Providers](Providers).
|
||||
- **LLM API key**: stored encrypted.
|
||||
- **Maximum note length**: a friendly dropdown that frames the LLM output cap in minutes of speech (5 / 10 / 20 / 30 / 60). Internally this sets the LLM max-tokens value. A custom token value entered in Advanced shows here as a "Custom" option.
|
||||
- **Transcription model / LLM model**: a single adaptive field. When the provider supports listing models and the cache is populated, it is a dropdown with a Refresh button and a "Custom..." escape hatch for typing an id by hand; otherwise it is a plain text field. Whichever is shown, the value is the model id sent to the provider. See [Providers](Providers) for which providers support the dropdown.
|
||||
- **Advanced** (collapsible):
|
||||
- **Transcription language**: an optional language hint passed to the transcription provider.
|
||||
- **LLM max tokens**: the raw output-token cap that "Maximum note length" frames in minutes. Editing it here updates the dropdown on the next render. The cap bounds output (note length), not input.
|
||||
|
||||
## Local whisper.cpp server (desktop)
|
||||
|
||||
Shown on desktop only. Manages a whisper-server binary you supply for fully on-device transcription. Fields: **Binary path**, **Model path**, **Port** (default 8080), **Extra args**, and a live **Status** row with Start/Stop and a log viewer. The server is always bound to loopback (`127.0.0.1`); it refuses to start if Extra args contains a non-loopback `--host`. Full walkthrough on [Self-hosting: whisper.cpp](Self-Hosting-Whisper).
|
||||
|
||||
## Templates
|
||||
|
||||
- **Templates folder**: where the template Markdown files live (default `ReWrite/Templates`). Changing it reloads templates from the new location.
|
||||
- **Populate or update default templates**: three buttons sharing one row:
|
||||
- **Populate**: creates any missing default templates plus `SharedCore.md` and the template guide. Non-destructive; skips anything that already exists.
|
||||
- **Update**: reconciles your default-derived templates against the current built-ins with a per-field 3-way merge, and writes a `Template update report.md` for anything it cannot safely auto-merge. Recreates any default you deleted.
|
||||
- **Load prior versions**: drops earlier shipped versions of the defaults into the folder as separate, selectable templates so you can compare wording.
|
||||
- **Default template**: the template pre-selected when you open the modal.
|
||||
- **Quick record (set template)**: the template used by the "Quick record (set template)" command (see [Commands and menus](Commands-and-Menus)).
|
||||
- **On filename collision**: when a `newFile` template would overwrite an existing note, either `auto` (silently append `-1`, `-2`, ...) or `prompt` (ask you for a name).
|
||||
|
||||
See [Creating templates](Creating-Templates) for the file format and how Populate / Update / Load prior versions differ.
|
||||
|
||||
## Recording
|
||||
|
||||
- **Audio format preference**: a hint for which container/codec MediaRecorder should prefer; the plugin falls back to a supported format if the preferred one is unavailable.
|
||||
- **Attachments folder**: where recorded audio is saved. Leave empty to use Obsidian's own attachment location; set a folder to override it. Saved recordings are linked into the output with an `![[...]]` embed.
|
||||
|
||||
## Ad-hoc instructions
|
||||
|
||||
Controls spoken "assistant" instructions extracted from a transcript (say the assistant name followed by a directive, and that directive is injected into the cleanup prompt).
|
||||
|
||||
- **Enabled**: turns the feature on or off.
|
||||
- **Assistant name**: the trigger word the extractor listens for (the vocative, for example "Scribe, make this a bulleted list").
|
||||
- **Assistant prompt file**: the vault Markdown file whose body is prefaced above extracted directives (default `ReWrite/AssistantPrompt.md`).
|
||||
- **Populate default assistant prompt**: writes the default prompt file if missing.
|
||||
|
||||
## Shared core
|
||||
|
||||
The baseline cleanup rules prepended to every template prompt (unless a template opts out). A status badge shows whether it is currently enabled (the file exists and is non-empty).
|
||||
|
||||
- **Shared core file**: the vault Markdown file used (default `ReWrite/SharedCore.md`). Delete or empty it to disable the shared core globally.
|
||||
- **Re-create shared core file**: writes the default shared core if missing.
|
||||
|
||||
See [Creating templates](Creating-Templates) for how the shared core combines with a template at run time.
|
||||
|
||||
## Known nouns
|
||||
|
||||
Proper nouns the LLM should preserve verbatim (with optional misheard variants).
|
||||
|
||||
- **Known nouns file**: the vault Markdown file used (default `ReWrite/KnownNouns.md`). Its frontmatter is human-guidance only and is never sent to the LLM; only the body lines are used.
|
||||
- **Populate default known nouns**: writes the default file (with example entries) if missing.
|
||||
|
||||
[Back to Home](Home)
|
||||
35
wiki/Troubleshooting.md
Normal file
35
wiki/Troubleshooting.md
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
# Troubleshooting
|
||||
|
||||
Start here, then follow the link into the page with the detail for your problem.
|
||||
|
||||
## Setup and configuration
|
||||
|
||||
- **The modal blocks recording/pasting with a setup card.** The active profile is missing a provider, model, key, or (for `openai-compatible`) a base URL. Fill in the highlighted fields. See [Settings reference](Settings-Reference) and [Providers](Providers).
|
||||
- **No templates in the dropdown.** You have not populated them yet. Settings, Templates, Populate. See [Quick start](Quick-Start).
|
||||
- **The plugin asks for a passphrase / says it is locked.** You are in passphrase encryption mode and the key is not unlocked. Enter your passphrase. See [Secrets and sync](Secrets-and-Sync).
|
||||
- **Keys disappeared after syncing to another device.** Encrypted keys do not decrypt cross-device in some modes; this is expected. Re-enter the key on that device, and consider excluding `secrets.json.nosync` from sync. See [Secrets and sync](Secrets-and-Sync).
|
||||
|
||||
## Provider errors
|
||||
|
||||
- **An error names the provider and an HTTP status.** That is the provider rejecting the request (bad key, wrong model id, rate limit, oversized audio). Read the message; it is attributed to the provider on purpose.
|
||||
- **"Maximum note length" / max-tokens error.** Your output cap is above the model's limit. Lower it in the profile. See [Providers](Providers).
|
||||
- **Recording too large.** You hit a provider's size or duration ceiling. Switch to a higher-ceiling provider (AssemblyAI, Rev.ai) or shorten the clip. Limits are listed in [Providers](Providers) and [Commands and menus](Commands-and-Menus).
|
||||
|
||||
## Recording
|
||||
|
||||
- **"No audio detected" warning.** The mic is muted, dead, or not granted permission for several seconds. Check your OS mic permissions and input device.
|
||||
- **Recording stops when the screen sleeps (mobile).** A WebView limitation, mitigated by a wake lock. See [Mobile](Mobile).
|
||||
|
||||
## Self-hosted whisper.cpp
|
||||
|
||||
Port conflicts, antivirus, startup timeouts, the loopback refusal, and FUTO `-ac` issues are all covered on [Self-hosting: whisper.cpp](Self-Hosting-Whisper#troubleshooting).
|
||||
|
||||
## Self-hosted / local LLMs
|
||||
|
||||
Connection refused, 404 on the `/v1` path, model-not-found, LAN access, and truncated output are covered on [Self-hosting: local and remote LLMs](Self-Hosting-LLMs#troubleshooting).
|
||||
|
||||
## Still stuck?
|
||||
|
||||
Open an issue on the [repository](https://github.com/WiseGuru/ReWrite-Voice-Notes/issues) with the provider, the exact error text, and what you were doing. For self-hosted setups, include the relevant log tail.
|
||||
|
||||
[Back to Home](Home)
|
||||
1
wiki/_Footer.md
Normal file
1
wiki/_Footer.md
Normal file
|
|
@ -0,0 +1 @@
|
|||
These pages are generated from the [`wiki/` folder in the ReWrite-Voice-Notes repo](https://github.com/WiseGuru/ReWrite-Voice-Notes/tree/master/wiki). Edits made directly in the wiki are overwritten on the next sync. To fix or improve a page, edit the matching file in `wiki/` and open a pull request.
|
||||
21
wiki/_Sidebar.md
Normal file
21
wiki/_Sidebar.md
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
### ReWrite (Voice Notes)
|
||||
|
||||
[Home](Home)
|
||||
|
||||
**Getting started**
|
||||
- [Quick start](Quick-Start)
|
||||
|
||||
**Reference**
|
||||
- [Settings reference](Settings-Reference)
|
||||
- [Commands and menus](Commands-and-Menus)
|
||||
- [Creating templates](Creating-Templates)
|
||||
- [Providers](Providers)
|
||||
|
||||
**Self-hosting**
|
||||
- [whisper.cpp](Self-Hosting-Whisper)
|
||||
- [Local and remote LLMs](Self-Hosting-LLMs)
|
||||
|
||||
**Help**
|
||||
- [Secrets and sync](Secrets-and-Sync)
|
||||
- [Mobile](Mobile)
|
||||
- [Troubleshooting](Troubleshooting)
|
||||
Loading…
Reference in a new issue