How am i driving
Score your Claude prompting
npx -y skills add brunodantas/how-am-i-driving --skill how-am-i-drivingAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Score your recent Claude Code prompting and produce a graded, evidence-backed report card — how good were my prompts, measured? Reads your recent session transcripts, computes deterministic measures (prompt length, prompts/session, context front-loading), then judges the semantic measures (rework rate, clarification, steering) and five 1–5 qualitative grades with quoted evidence. Renders a Markdown Full Report, an optional HTML report, and a shareable HTML Scorecard (scores only, no quotes). Use when the user asks "how am I driving", "grade my prompting", "score my prompts", "make a scorecard", or wants measured feedback on their own Claude Code prompting.
SKILL.md
11.5 KB, ~2.7k tokens by cl100k_base, as published. Nobody here has run it
How Am I Driving
A graded report card on the user's own Claude Code prompting — "how good were my prompts, measured?" Credibility comes from concrete measures and quoted evidence, not vibes. Voice: an encouraging coach with light driving-themed garnish; honest underlying numbers.
Scope: mechanical (deterministic) measures, the semantic / qualitative judged layer, the Markdown Full Report, the HTML render modes — the shareable Scorecard and an optional HTML Full Report — and the distribution surface: a Claude Code plugin, a
curl … | bashinstaller, and manual clone. SeeCONTEXT.mdanddocs/adr/.
What counts as a prompt
A genuine, human-typed prompt — a type:"user" transcript entry that is
plain typed text. Tool results, slash-command wrappers, injected skill
instructions (isMeta), task-notification events, /compact continuation
summaries, and interrupt markers are not prompts and are filtered out by
analyze(). Rewinding or resuming a session re-logs earlier turns with the same
uuid; analyze() de-duplicates those replays by uuid so a long, resumed
session isn't counted several times over (genuinely repeated prompts like a
second "Yes" carry distinct uuids and are kept). The report always states the
actual prompt count analyzed, so a thin sample reads as a soft signal.
Measured vs judged
Two kinds of measure, and the report labels every number as one or the other:
- Measured — deterministic counts from
analyze()(prompt length, prompts/session, context front-loading). Same corpus in → same numbers out. - Judged — you, Claude, read the prompts and score them against the fixed rubric below. These are the semantic counts (rework, clarification, steering) and the five qualitative grades. A re-run can shift a judged score by a point; that's expected, and the labelling makes it read as such, not as a bug.
Never present a judged number as if it were measured, and never recompute the measured numbers yourself — the script is the single source of truth for those.
Flow
Mechanical analysis is deterministic; the judged layer is you scoring the extracted prompts in the middle. So a deep read is three steps: compute → judge → render. Work in a scratch dir (e.g. the session scratchpad).
Paths are relative to this skill's directory. The
python3 scripts/…commands below assume your working directory is this skill's own folder (the base directory shown when the skill loads — e.g.~/.claude/skills/how-am-i-driving/), not the user's project.cdinto it first, or prefix the script path with that directory, soscripts/report.pyresolves wherever the skill is installed.
1. Resolve depth and corpus
- Depth.
--deepis the default and the right choice for ~10 sessions: full semantic judgment with evidence. Use--fastonly when the user asks for it or the corpus is large (say ≳40 sessions), where a light semantic pass (headline rework only, no qualitative grades) keeps cost down. - Corpus. Default = the most recent 10 sessions across all projects. A
numeric argument overrides the count (e.g.
/how-am-i-driving 50).
2. Compute once — emit the analysis seam
python3 scripts/report.py [count] --depth deep --emit-analysis > "$SCRATCH/analysis.json"
This is the single analysis pass. analysis.json holds the resolved corpus, the
mechanical metrics, and prompts — the extracted genuine-prompt sequence you'll
judge. Do not re-resolve or re-analyze later; phase 3 renders from this exact
file ("compute once, render twice").
If metrics.prompt_count is 0, skip judging and just render — the report handles
the empty corpus gracefully.
3. Judge the prompts → write judgment.json
Read analysis.json. Each prompts[i] has text, session_id, and
index_in_session. Judge the whole sequence in order, per session, so you
can see a redirect follow the attempt it corrects.
Score these and write a judgment.json matching the schema below.
Semantic counts (judged)
- Rework rate — the headline. Count prompts where the user re-prompts to
correct or redirect Claude after a missed or partial attempt. Crucially,
count implicit and polite rework, not just literal "no, I meant…":
- "actually, can you also…", "hmm, that's not quite it", "let's try a different approach", "can you redo the X part", re-explaining the same ask in new words, or re-attaching context that should have landed the first time.
- A fresh next step ("now add tests") is not rework. A genuine new task is not rework. Approvals ("looks good, ship it") are not rework.
- Leave
ratenull — the renderer derives it from the prompt count.
- Clarification rate. Count prompts that exist because Claude asked a question back (the user is answering a clarifying question) — a signal the previous prompt was under-specified.
- Steering interventions. Count mid-task interrupts / course-corrections (e.g. "stop", "wait — not like that", redirecting while work is in flight).
Qualitative grades (judged, 1–5, with evidence)
Score each measure 1–5 against the fixed rubric, and back each score with a
verbatim quoted prompt from the user's own transcripts (evidence_quote,
plus its evidence_session_id). Pick a quote that genuinely typifies the score.
| Measure | 1 — needs work | 3 — solid | 5 — excellent |
|---|---|---|---|
| specificity | Vague gestures ("fix this", "make it better"); no nouns, no constraints | Mostly clear asks; some ambiguity Claude has to resolve | Precise: named files/symbols, explicit constraints, scoped — no guessing needed |
| context_quality | Asks land with no files/specs/errors; Claude must hunt or guess | Relevant context usually present, occasionally thin | The files, specs, errors, and background needed to act arrive with the ask |
| decomposition | One sprawling do-everything ask, or thrash with no plan | Reasonable steps, occasionally over/under-scoped | Work broken into coherent, right-sized steps at a workable altitude |
| goal_clarity | Only the next keystroke; no sense of done | End state implied but not stated | The desired end state is explicit — Claude can tell when it's finished and verify |
| correction_style | Redirects are vague/late/blame-y, or the user silently re-does work | Corrections clear but sometimes late | Redirects are specific, prompt, and blame-free: what was wrong, what you want instead |
In --fast mode, skip the qualitative grades entirely and judge only the
headline rework (optionally clarification). Leave qualitative an empty list and
set depth to "fast".
judgment.json schema
{
"depth": "deep",
"rework": { "count": 0, "rate": null, "note": "one-line summary (optional)" },
"clarification": { "count": 0, "rate": null },
"steering": { "count": 0 },
"qualitative": [
{
"measure": "specificity",
"score": 4,
"evidence_quote": "<verbatim prompt text from analysis.json>",
"evidence_session_id": "<that prompt's session_id>",
"rationale": "one line on why this score"
}
// ...one entry per measure: specificity, context_quality,
// decomposition, goal_clarity, correction_style
]
}
Quote the user's prompts verbatim — evidence_quote must be real text from
analysis.json, never paraphrased or invented. (Evidence appears only in the
private Full Report, never in the future shareable Scorecard.)
4. Render the Full Report
python3 scripts/report.py --render "$SCRATCH/analysis.json" --judgment "$SCRATCH/judgment.json"
Present the Markdown it prints unedited. It already carries the coach voice, the honest sample-size line, every measure's inline help text, the measured / judged labelling, and your quoted evidence. Do not re-summarize or recompute.
For a quick mechanical-only read (no judging), python3 scripts/report.py [count] still renders the measured section on its own.
5. Render modes — Scorecard and HTML (optional, same analysis pass)
Both HTML modes render from the same analysis.json + judgment.json
(ADR-0003) — never re-resolve or re-judge to produce them.
-
Scorecard (
--scorecard) — a self-contained, shareable HTML card at a fixed 1200×630 social ratio: scores and grades only, no quoted prompts (the privacy guarantee). Render it when the user asks for something shareable:python3 scripts/report.py --render "$SCRATCH/analysis.json" \ --judgment "$SCRATCH/judgment.json" --scorecard > "$SCRATCH/scorecard.html"Write it to a file and tell the user the path; it's designed to be opened and screenshotted. Because it carries no quotes, it's safe to share publicly.
-
HTML Full Report (
--html) — the same private Full Report as Markdown, including evidence quotes, as a styled standalone HTML page. Use when the user wants the detailed report in HTML rather than Markdown.
Both flags also work on the one-shot mechanical path (no --judgment).
Architecture (for maintainers)
Single deterministic seam, AnalysisResult, plus its judged sibling Judgment
(ADR-0002, ADR-0005):
scripts/analyze.py—analyze(corpus) -> AnalysisResult. Corpus resolution, genuine-prompt filtering, mechanical metrics. Deterministic.scripts/models.py— theAnalysisResult(measured) andJudgment(judged) data contracts.Judgmentis plain data Claude emits as JSON.scripts/render_shared.py— content and formatters every renderer shares: the per-measure help text, the ordered qualitative-measure list, and the number/percentage/duration/grade-bar helpers. Neutral home so no renderer reaches into another's internals.scripts/render_full_report.py—render_full_report(result, judgment=None) -> str. Pure function, Markdown out, measured + judged sections.scripts/render_html.py—render_scorecard()andrender_html_report(). Pure functions, self-contained HTML out, over the sameAnalysisResult+Judgment(ADR-0003). The Scorecard carries scores only — no quoted prompts.scripts/report.py— CLI glue:--emit-analysis(phase 1),--render+--judgment(phase 3),--depth deep|fast,--scorecard/--html.tests/— fixture-drivenpytest. The deterministic analysis and the renderers are tested; the judgment itself is deliberately not unit-tested (it's non-deterministic by design — validated by example/eval). Run withpython3 -m pytest.
Mechanical measures are deterministic Python (never regex-as-primary, never LLM — ADR-0002). The semantic/qualitative measures are Claude's judgment, anchored by the rubric above and labelled judged to keep the distinction honest.