sminer

Find the corrections you keep making to Claude,
and fix them for good.

$ go install github.com/rossedman/sminer/cmd/sminer@latest
~ zsh
$ sminer run --offline -o report.md
· ingested 4,212 lines from 318 sessions
· finding signals, clustering
· analyzed: 9 findings, 3 new
$ sminer finding list
Fc72cc0 hook Never hand-edit lockfiles
Fcd5b9b claude_md Table tests, not testify
F15ec9e skill Lint and test, then commit
$ sminer finding accept Fc72cc0
  • <30 sfor 90 days of transcripts
  • 7kinds of friction it detects
  • ~2 KBper classifier call, or none
  • 0files edited behind your back

The problem

You've said it before.
It's on disk.

You correct Claude for the same things across repos and weeks: test style, lockfile edits, naming conventions. Each correction costs a turn and some attention, and every one of them is already written down in your session transcripts. Nobody reads them.

sminer reads them. It finds the pushback, interrupts, rewinds and repeated instructions, groups them by the rule underneath, and ranks them by how often they happen and across how many repos.

  • Evidence for every finding: counts, repos, excerpts
  • One finding per rule, with an ID that survives re-runs
  • A patch for each fix, never applied for you
Fc72cc0hook score 27

Never hand-edit package-lock.json

9 occurrences in 7 sessions · 3 repos · Sep 23 – Oct 14
stop editing package-lock.json directly. regenerate it with npm install correction · web · claude --resume b2222222…
never hand-edit lockfiles, revert that and run npm install correction · api · claude --resume a4444444…
PreToolUse on Edit|Write|MultiEdit, block when file_path matches (^|/)package-lock\.json$

From friction to fix

The right remedy for each rule.
Deterministic beats instructed.

When a rule can be checked mechanically, sminer proposes a hook. When it needs judgment, a CLAUDE.md line. When you keep re-explaining a procedure, a skill. Anything you already have is left out.

Hook

a file path or a command can enforce it

A PreToolUse script for your hooks directory, plus the settings.json entry that registers it.

if grep -Eq '(^|/)package-lock\.json$'; then
  echo 'Blocked: run npm install' >&2
  exit 2
fi

CLAUDE.md line

judgment or style the model must apply

A diff appending the rule to the repo's CLAUDE.md, or the global one when it spans repos.

 ## Learned conventions

+- Write table-driven tests with the
+  standard library, not testify.

Skill

a procedure you keep re-explaining

A draft SKILL.md with the steps you typed out in session after session, ready to edit.

---
name: pre-commit
description: Before any commit
---
1. make lint  2. make test
3. conventional commit

How routing works

Why sminer

Guardrails from evidence,
not from memory.

Seven kinds of friction

Corrections, interrupts, rejected tool calls, rewinds, repeated instructions, hook blocks, failure loops and manual fix-ups. Cheap heuristics first; the model only confirms candidates.

Private by default

Secrets are redacted before anything is stored, and transcripts are never copied. --offline keeps everything local; otherwise only about 2 KB per candidate goes to the classifier.

Fast and incremental

Each run reads only what's new since the last one. Ninety days of transcripts take well under thirty seconds on a laptop; a repeat run takes a few.

Proposals, not edits

Accepting a finding writes a patch file. You review it and apply it. sminer never touches your CLAUDE.md, settings or hooks.

Proof the fix worked

sminer finding trend splits each finding's weekly rate at the day you adopted the fix, so you can see the correction stop happening.

Made for scripts too

--json on every command, data on stdout and logs on stderr, documented exit codes, and shell completion of live finding IDs.

Quick start

From transcripts to a fix
in four commands.

sminer is a single Go binary with no cgo and no setup: it finds Claude Code's transcripts in ~/.claude/projects on its own. Start offline, then add an API key for sharper results.

Full getting-started guide
  1. Install

    $ go install github.com/rossedman/sminer/cmd/sminer@latest
  2. Mine your transcripts, offline

    Nothing leaves your machine. The report goes to stdout, or a file with -o.

    $ sminer run --offline -o report.md
  3. Optional: let the model confirm candidates

    $ export ANTHROPIC_API_KEY=...
    $ sminer run -o report.md
  4. Preview a fix, then accept it

    $ sminer finding accept Fc72cc0 --preview
    $ sminer finding accept Fc72cc0   # prints the patch path

How it works

A batch pipeline on your machine.
One optional network call.

Each stage reads from and writes to a local SQLite file, so any stage can be re-run on its own. Only the classifier leaves the machine, and --offline turns it off.

Transcripts flow through ingest, signal, classify, cluster, remedy and report, all on your machine around a SQLite store. Only classify calls the Anthropic API, about 2 KB per candidate. Local embeddings feed clustering; your CLAUDE.md, hooks and skills are read to avoid duplicate proposals.
Tap to open the full-size diagram

Read the stage-by-stage tour

Commands

A small CLI that
reads like a sentence.

Every command has --help with examples, --json for scripts, and errors that tell you what to run next.

Mining

run
Ingest, analyze and print the report
ingest
Read new transcript lines, redacted
analyze
Signals, classifier, clusters, remedies
report
The ranked report, Markdown or JSON

Findings

finding list
Open findings, highest score first
finding show
The proposal and every excerpt
finding accept
Write the patch; --preview to look first
finding dismiss
Hide one that isn't worth fixing
finding reopen
Undo accept or dismiss
finding trend
Weekly rate, before and after

Other

config show
Every setting and where it came from
config path
Where the config file lives
eval
Score detection on a labelled set
version
Build info and the command tree
completion
bash, zsh, fish and PowerShell

Full CLI reference

Stop repeating yourself.

Free and open source under the MIT license.