pastilhas 45ec9dc820 AGENTS.md, so both harnesses find the same guidance
opencode discovers AGENTS.md and nothing else; claude code discovers CLAUDE.md.
this repo had neither, so an agent sent to change something here arrived with no
guidance at all under either.

it deliberately does NOT repeat README.md. that file says what the plugin is,
for someone deciding whether to install it. this one answers the other question:
i have to change something in here, what will i break.

the facts in it are read from the repository rather than recalled — the panel
keys from web/panels.ts, the tables from db/schema.ts, the permission keys, the
host binaries and the route claims from manifest.ts. presence is the declaration
everywhere in this system, so the file says what the platform will actually
conclude from these files existing.

CLAUDE.md beside it is a pointer, not a copy: two copies drift and the stale one
is the one somebody reads.
2026-08-27 07:24:18 +00:00

Transcribe

Officer's speech-to-text, talking to a self-hosted whisper.cpp server.

Transcribe does not run Whisper and ships no model. You point it at a whisper.cpp /inference server you already run and it forwards to it, tuned for one person talking into a phone: detect the spoken language, then transcribe faithfully in it — never translated, never guessed at in English when the audio is not.

What you get

  • POST /api/transcribe/transcribe — send an audio file, get back its text and the language Whisper detected. Two-pass under the hood (detect, then transcribe in that language) so a low-confidence guess never quietly defaults to English.
  • Conversations come back as conversations. Nobody declares what a recording is — a probe on the diarization worker runs alongside every transcription and finds out. Solo dictation returns as paragraphs, exactly as before; a recording with several voices returns speaker-labeled (Speaker 1: …) with conversation: true and a speaker count. The worker is optional: without it, or if it fails mid-request, everything still transcribes — just never labeled. See ~/dockers/torch-worker for the worker itself.
  • Fair queueing for a multi-user server. Transcription and diarization each run one job at a time behind their own queue, in arrival order — and on different hardware, so the conversation probe costs a solo memo nothing.
  • A file-browser task. Right-click an .mp3, .wav or .m4a and transcribe it without a model turn — the task is a plain script that calls this plugin's own route and files the result next to the original.
  • A skill, so an agent asked to transcribe something knows the route, the shape, and what to say when nothing is configured, without being told.

What you need

A whisper.cpp server you already run, reachable from this machine, answering POST /inference — the same container the platform used to talk to directly. Nothing else. No system packages, no host binaries; the sidecar reaches it with fetch.

Setup

PUT /api/transcribe/config
{ "url": "http://192.168.1.50:64201" }

Validated against the server before it is stored — a wrong URL is a 400 with the reason, not a saved value that fails on the first real transcription.

What this plugin deliberately does not have

  • No dashboard route, no dock tile. There is nothing to look at — this is reached through the file browser's task menu and by an agent that has read the skill, not through a screen. Shipping no web/ is a supported shape, not an oversight.
  • No streaming. One file in, one answer back. If you want a live microphone, that is a different feature built on top of this one, not something this plugin does today.
  • No translation. It transcribes in whatever language was spoken. Whisper's own translate mode is English-only, so honouring "translate into <language>" for anything else would mean silently handing back a rough English rendering of, say, Portuguese audio — worse than refusing.
S
Description
Speech to text for Officer — audio files transcribed through a Whisper server
Readme
132 KiB
Languages
TypeScript 100%