npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

qvac-pocket-tune

v0.1.0

Published

Fine-tune a personal LoRA adapter on your own notes and chats, entirely on-device with Tether QVAC, and share it peer-to-peer.

Readme

Pocket Tune

Teach a small language model your voice, on your own device. Point Pocket Tune at your notes, a WhatsApp export or an FAQ. It turns them into a training set, scrubs secrets and identifiers, then trains a LoRA adapter locally with Tether QVAC's on-device fine-tuning. Your data never leaves the machine.

The result is a ~20 MB adapter you can chat with, compare against the base model, and (if you want) share peer-to-peer as a pear:// link through qvac-seed.

$ pocket-tune prep examples/pirate-voice/faq.csv --out runs/pirate --system "You are Captain Byte."
✔ SFT dataset written to runs/pirate
  12 train / 2 eval conversations (dropped: 0 duplicate, 0 too long, 0 empty)

$ pocket-tune train runs/pirate --epochs 8
▸ epoch 8 train batch 48/48  loss 0.409  acc 0.715  eta 0s
✔ adapter: runs/pirate/trained-lora-adapter.gguf (20.2 MB)

$ pocket-tune compare runs/pirate "Say hi" "What should I eat for dinner?"
❯ Say hi
  base : Hello! How can I assist you today?
  tuned: The first mate of Byte! And the sailor of the bytes!
❯ What should I eat for dinner?
  base : For dinner, consider a balanced meal with vegetables, proteins, and a main dish. Options include…
  tuned: Bread and eggs.

(Real output from a MacBook (Apple Silicon GPU) with Qwen3-0.6B. Training 8 epochs on 14 examples took a few minutes. With 14 examples you get a style shift, not a personality clone. Bring a few hundred real conversations for that.)

Why

QVAC can fine-tune LoRA adapters on laptops and phones (including BitNet models on mobile GPUs), but finetune() expects a clean JSONL file and a compatible base model. Getting from "my notes" to a working adapter is the hard part:

  • Sources people actually have. Markdown/Obsidian notes, WhatsApp exports (Android and iOS formats, multi-line messages, media lines), chat JSON/JSONL, and Q&A CSVs.
  • Your messages become the assistant turns. Pass --me "Your Name" and your replies become the training targets. Silences longer than an hour start a new conversation.
  • Scrubbing before training. Emails, phone numbers, wallet addresses, private keys, API tokens, IBANs, card numbers and BIP-39 seed phrases are replaced by placeholders. LoRA weights can memorise text, and adapters get shared.
  • Dataset hygiene. Near-duplicate removal, context-length filtering, and a deterministic train/eval split, so re-running gives the same split.
  • Compatibility checks. QVAC only fine-tunes qwen3, gemma3 and bitnet models in F32/F16/Q4_0/Q8_0/TQ1_0/TQ2_0. Pocket Tune checks this before you download gigabytes (many catalog models are Q4_K_M and would fail).
  • A memory check before downloading. QVAC's assessModelFit() measures the base model against this device's free memory using the registry's tensor list (tens of KB), never the weights. Pocket Tune refuses a model that likely won't fit (--force overrides). Training needs extra headroom on top of the model, so "likely fits" is necessary but not sufficient.
  • Pause and resume. Ctrl+C pauses at the next step and saves a checkpoint, and pocket-tune resume continues from it. That suits phones and laptops on battery.
  • An adapter card. adapter.json records the base model (name and sha256), hyperparameters, metrics and dataset hashes. It never contains the data itself.

Install

npm install -g qvac-pocket-tune          # puts `pocket-tune` on your PATH
npm install qvac-pocket-tune   # library (Node), or `qvac-pocket-tune/core` anywhere

From source: git clone https://github.com/lopeselio/qvac-pocket-tune && cd qvac-pocket-tune && npm install.

Node.js 22+. The base model downloads on first use (Qwen3-0.6B is 382 MB).

Usage

pocket-tune prep <files/dirs...> --out <run> [--me "Your Name"] [--system "..."]
                 [--type notes|whatsapp|chat-json|qa-csv] [--eval 0.1] [--no-scrub]
pocket-tune train <run> [--model tiny] [--epochs 2] [--lr 1e-4] [--ctx 512] [--cpu] [--force]
pocket-tune resume <run>
pocket-tune chat <run> [--base]
pocket-tune compare <run> "prompt one" ["prompt two"...]
pocket-tune share <run> --name <adapter-name> [--no-seed]
pocket-tune models

| Data | Becomes | Notes | |---|---|---| | notes/ (.md, .txt) | causal (plain text) | Front matter, code blocks, images and link syntax are stripped | | WhatsApp Chat with Sam.txt | SFT conversations | Needs --me "Your Name" exactly as it appears in the export | | *.json, *.jsonl | SFT conversations | {messages:[{role,content}]} per line, or a JSON array | | *.csv | SFT Q&A pairs | Columns named question/answer, prompt/response or input/output |

Notes and chats can't be mixed in one run, because QVAC trains either SFT or causal. Prep them into separate runs.

Base models

| Preset | Model | Mode | | |---|---|---|---| | tiny (default) | Qwen3 0.6B Q4_0, 382 MB | SFT | phone-friendly | | small | Qwen3 1.7B Q4_0, 1.1 GB | SFT | phone-friendly | | bitnet | BitNet b1.58 0.7B TQ2_0, 217 MB | causal | phone-friendly | | bitnet-1b | BitNet b1.58 1B TQ2_0, 835 MB | causal | phone-friendly | | bitnet-3b | BitNet b1.58 3B TQ2_0, 1.9 GB | causal | desktop |

You can also pass any QVAC model constant or a local .gguf that meets the requirements above.

Sharing

pocket-tune share runs/pirate --name pirate-voice
# adapter: pear://9c1e…/pirate-voice/adapter.gguf
# card:    pear://9c1e…/pirate-voice/adapter.json

Only the adapter and its card are published. Anyone can then fetch it, verified, with npx qvac-seed fetch <url> and load it on the same base model via modelConfig.lora.

Mobile app

mobile/ is an Expo app with the same flow on a phone: pick files, build a scrubbed dataset, fine-tune on the phone's GPU (with memory check, pause and resume), then compare the base and adapted answers. It bundles the same core module as the CLI. QVAC needs a physical device; see mobile/README.md.

Library

The parsing, scrubbing, dataset and fine-tune-option code has no Node built-ins and is exported separately as qvac-pocket-tune/core, which the mobile app bundles.

import * as sdk from '@qvac/sdk'
import { prep, train, compare } from 'qvac-pocket-tune'

await prep(['./notes'], { outDir: 'runs/notes' })
const res = await train({ sdk, runDir: 'runs/notes', model: 'bitnet', hyper: { numberOfEpochs: 3 } })
console.log(res.adapter, res.card.metrics)

Caveats

  • Scrubbing is a best-effort, regex- and wordlist-based filter, not a guarantee. Review train.jsonl before training on sensitive material, and before sharing an adapter.
  • An adapter only works with the exact base model it was trained on. The card records that model's sha256.

Development

npm test   # parsers, scrubber, dataset builder, trainer (fake SDK), chat/compare, share via qvac-seed

License

Apache-2.0