kenzotp/voicecard

Turn a rambling voice-note transcript into resolved, actionable items. Keeps the version you actually meant when you talk yourself out of something mid-sentence.

3

stars

3

commits

JavaScript

primary language

Aug 25, 2026

updated

README

voicecard

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.

$ 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.

Why

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.

Install

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.

Usage

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 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.

Does it actually work?

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:

  1. "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.
  2. "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.
  3. 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 tuning history, kept honest

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.

Roadmap

Longer term I'd like to wire this into Jira, Linear, or Monday-style boards, and possibly into Zuuna, 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.

Background

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.

License

MIT

Contributors

kenzotp

3 commits

kenzotp/voicecard

Turn a rambling voice-note transcript into resolved, actionable items. Keeps the version you actually meant when you talk yourself out of something mid-sentence.

3

stars

3

commits

JavaScript

primary language

Aug 25, 2026

updated

README

voicecard

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.

$ 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.

Why

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.

Install

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.

Usage

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 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.

Does it actually work?

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:

  1. "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.
  2. "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.
  3. 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 tuning history, kept honest

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.

Roadmap

Longer term I'd like to wire this into Jira, Linear, or Monday-style boards, and possibly into Zuuna, 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.

Background

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.

License

MIT

Contributors

kenzotp

3 commits

Languages

JavaScript

100.0%