# Show HN: Voicecard – a CLI that resolves contradictions in rambling voice notes

> Source: <https://github.com/kenzotp/voicecard>
> Published: 2026-08-25 10:56:59+00:00

Turn a rambling voice-note transcript into resolved, actionable items. The part every "AI extracts your tasks" tool gets wrong: when you talk yourself out of something mid-sentence, voicecard keeps only what you actually meant at the end.

``` bash
$ echo "I'm going to the store to get grapes today, no actually I'm getting apples." | voicecard
{
  "items": [
    { "kind": "card", "text": "Get apples from the store" }
  ]
}
```

Not "grapes and apples." Not "grapes" (caught the first mention and stopped listening). The model has to track the note as a whole and understand that grapes was retracted, not just transcribe and keyword-extract. Most meeting-note and voice-memo tools are built for accurate transcription and summarization, not for noticing that a speaker overturned their own earlier statement. This one is built specifically for that.

Grew out of a working personal system for turning voice notes into board tickets: dictate on the go, get it auto-sorted, never lose a thought to "I'll write it down later." The one thing that decides whether that's trustworthy is contradiction handling. A tool that files the version of the task you talked yourself out of creates noise instead of removing it.

```
npm install -g voicecard
```

Needs Node 18+. That's the only hard dependency. Everything else is either already on your machine (a local model) or a key you bring yourself.

```
voicecard notes.txt              # from a file
cat notes.txt | voicecard        # from stdin
voicecard --help                 # all options
```

Two modes, your choice, zero hosting on my end either way:

**Local**(default): runs against a local[Ollama](https://ollama.com)model.`ollama pull qwen2.5:7b`

and it works out of the box, fully offline. Nothing leaves your machine.**Bring your own key**:`OPENAI_API_KEY=sk-... voicecard notes.txt --provider byok`

uses your own OpenAI (or OpenAI-compatible) account. Your cost, your data relationship with that provider, not mine.

No hosted backend, no account, no telemetry. I don't see your transcripts either way.

Current score: **15 of 18** on my adversarial suite, running the small local model (qwen2.5:7b). The suite covers revisions, full retractions, partial list edits, chained double reversals, quantity changes, filler words that sound like corrections but aren't, and negative controls to catch over-correction (a tool that invents corrections would be worse than one that misses them).

You can run it yourself: `node experiments/adversarial-test.mjs`

(needs Ollama with qwen2.5:7b pulled). The suite imports the same prompt the CLI ships with, so it can't silently drift from what you're actually running.

What passes: substitutions, full retractions, double reversals, quantity changes, multi-topic notes where only one topic gets revised, additions that must not be mistaken for replacements, whole-note cancellations, repetition-for-emphasis staying one item, and both negative controls.

The three current misses, plainly:

- "Grab milk from the store, wait, what was I saying, anyway, also grab bread" drops the milk. The filler "wait" gets over-read as a retraction. This is the worst class of failure (silently losing an item) and it appeared as a side effect of fixing an earlier bug, which is documented below because that's how prompt tuning actually goes.
- "Call John, actually let's email instead" resolved to a card that still leads with "Call John" and puts the correction in parentheses. The retracted verb should not be the headline.
- Clearly actionable items occasionally come back classified as
`note`

instead of`card`

. The resolution is right, the label is too cautious.

I don't have a clean comparison against a frontier-class model. The one I tried (ox-alpha, on a free API tier) rate-limited on 3 of 7 calls mid-run, and that run was against an earlier prompt revision anyway. On the calls that went through, it agreed with the local model. What I can say honestly: a 7B model handles most of this task, which surprised me.

I also fed it a test meeting transcript I wrote: a PM and two devs argue over whether a feature is too big for one ticket, decide to split it, and negotiate who owns what. It split the tickets correctly, put the right details in each, and ignored a proposal that got argued down mid-meeting. It also dropped one explicitly stated assignee and flattened a specific scheduling reason into a generic priority claim. (That test uses its own task-specific prompt, in `experiments/meeting-transcript.mjs`

.)

The first prompt version failed two cases: a full retraction ("we still have milk, scratch that") produced a placeholder item describing the retraction itself, and repetition-for-emphasis split into two items with "it's urgent" becoming its own nonsense task. Both got fixed with worked examples in the prompt, and both fixes held on re-testing.

A third worked example fixed list merging ("milk, eggs, bread, and coffee" now comes back as four items, not one). But the retraction example now over-triggers on filler words in at least one case, which is miss number 1 above. Fixing a prompt failure by example can cause a different failure. If you fork this and tune further, re-run the whole suite, not just the case you fixed.

Longer term I'd like to wire this into Jira, Linear, or Monday-style boards, and possibly into [Zuuna](https://zuuna.de), a project management tool I run. None of that is required to use the CLI. Also on the list: bundled transcription (audio in, not just text), though the interesting problem here is resolving what you meant, and good Whisper wrappers already exist for the speech-to-text part.

The personal system this grew from: iPhone Shortcut, webhook, local Whisper transcription, this classification logic, auto-filed onto a project board. That setup depends on my own hardware and isn't what's published here. This CLI is the general, reusable core of it, rebuilt to run anywhere.

MIT
