Claude Code plugin reference
Reference for the Qualflare plugin for Claude Code: every /qf- command, the coverage nudge rules, state files, authentication and the formats it knows.
Last updated
This page lists the 8 slash commands of the Qualflare plugin for Claude Code, the rules of its coverage nudge, its state files and the format slugs it knows, with arguments, defaults and limits.
Installation
| Command | Description |
|---|---|
/plugin marketplace add Qualflare/qualflare-claude-code | Add the Qualflare marketplace |
/plugin install qualflare@qualflare | Install the plugin. It stays installed across sessions |
/plugin update qualflare | Upgrade to the latest version |
The plugin is qualflare, from the marketplace qualflare. It needs qf on your PATH, and Node.js for the coverage nudge.
Slash commands
| Command | Argument | What it does |
|---|---|---|
/qf-init | — | Sets up the project |
/qf-cover | [--all] [path or glob] | Writes tests for changed code |
/qf-run | [framework-slug | package/path [slug] | report-path [slug]] | Runs tests and uploads the results |
/qf-fix | [framework-slug or package/path] | Fixes failing tests from the last run |
/qf-doctor | — | Checks the setup |
/qf-update | [framework-slug or package/path] | Refreshes file counts |
/qf-state | — | Shows what the plugin knows |
/qf-hook | on|off | Turns the coverage nudge on or off |
/qf-init
/qf-init sets up a project once, from its root (a folder with .git/, package.json, go.mod or another manifest). In order, it:
- finds a monorepo's packages (npm or pnpm workspaces, or several
go.modorpyproject.tomlfiles); - detects each package's languages, frameworks and test-file counts, and asks you to confirm them;
- writes
.qualflare/test-state.md; - prints a
qf login <identifier>line per identifier not logged in, and waits fordoneorskip; - asks about the coverage nudge and writes
.qualflare/config.json; - writes a Qualflare block between
<!-- BEGIN qualflare-ai -->and<!-- END qualflare-ai -->inCLAUDE.md, changing nothing outside it.
An identifier is the package name lowercased, with characters outside [a-z0-9_-] turned into -, runs of - collapsed and the ends trimmed. pkg- is prefixed when the result is empty, starts with anything but a letter or digit, or is a qf command name such as login or help, and the identifier is cut to 63 characters: @acme/web becomes acme-web.
/qf-cover
/qf-cover writes tests for source files changed in the session that lack tests; a path or glob narrows them, and --all takes every source file in the path. It proposes 2 to 5 cases per function (a happy path, an edge case and, for error handling, an error case) and writes them once you approve. With --all, or in a project with no tests, it asks you to narrow to 8 files or fewer per round. It writes jest (Vitest imports when Vitest is a dependency), playwright, pytest, Go, RSpec, PHPUnit, JUnit or TestNG tests, and appends to an existing test file without removing a test.
/qf-run
/qf-run runs the frameworks in test-state.md and uploads each result with qf <identifier> collect. The first matching rule reads its argument:
- an exact slug from
test-state.mdruns that framework (/qf-run cypressruns Cypress even with acypress/folder); - a package path, or its start, runs that package, narrowed by a slug after it;
- an existing file, a glob, or a directory plus a slug is a report: it is uploaded, and nothing runs;
- anything else is read as a slug.
| Slug | What /qf-run runs | Uploads |
|---|---|---|
jest | npx vitest run with Vitest, else npx jest | Jest JSON |
mocha | npx mocha | Mocha JSON |
python | pytest | JUnit XML |
golang | go test ./... -json | Go test JSON |
playwright | npx playwright test | Playwright JSON |
cypress | npx cypress run; needs mochawesome as a dependency | Mochawesome JSON, one per spec |
rspec | bundle exec rspec | RSpec JSON |
phpunit | ./vendor/bin/phpunit | JUnit XML |
junit | mvn clean test or gradle cleanTest test | JUnit XML from every module |
cucumber | cucumber-js, bundle exec cucumber or mvn clean test | Cucumber JSON |
webdriverio | npx wdio run with the @qualflare/webdriverio reporter | One JSON per worker |
appium | npx wdio run with the @qualflare/appium reporter | One JSON per worker |
flutter | flutter test qf ≥ 0.2.0 (requires qf 0.2.0 or later) | Flutter JSON |
The CLI reads qualflare_flutter data (labels, steps, screenshots) qf ≥ 0.3.0 (requires qf 0.3.0 or later). Other slugs need a report you produce, uploaded with /qf-run <report-path> <slug>:
| Slugs | Report the CLI parses |
|---|---|
selenium, testcafe, karate, newman | The tool's JSON report |
k6 | k6 JSON end-of-test summary |
testng, maestro, espresso, xctest | JUnit XML; for xctest, not an .xcresult bundle |
zap, trivy, snyk | The tool's JSON output |
sonarqube | SonarQube issues export (JSON) |
Without a slug, /qf-run detects a report's format with qf validate (local, no login) and asks you to confirm. A report goes to the only identifier, or the one whose package path matches; otherwise /qf-run asks.
Before uploading, /qf-run deletes each framework's previous result, and checks qf version and, with qf projects, every login. It continues past failing tests, passes --branch and --commit from git, and never passes --environment, so results go to QF_ENVIRONMENT, or development when it is unset (Environments). It prints Uploaded to Qualflare ✅ only when every upload succeeded.
/qf-fix
/qf-fix reads the last /qf-run results in .qualflare/results/ and makes the smallest source change for each failing test. It edits source files, not tests, and skips a test whose assertion looks wrong. It then re-runs the affected frameworks once and reports what still fails. It makes no second pass and doesn't upload.
/qf-doctor
/qf-doctor checks the setup and prints a report with a fix for each problem:
| Check | Runs or reads | Result |
|---|---|---|
| CLI | qf version --short | ❌ when qf isn't found |
| Auth, per identifier | qf projects | ⚠️ when not logged in: qf login <identifier>, with a token from Project Settings > Access Tokens |
| Slug sync | qf list-formats against the plugin's slugs | ⚠️ for a slug only one side knows |
| Config | .qualflare/config.json | ❌ when missing or invalid |
| Hook registration | the plugin's hooks.json | ⚠️ when no Stop hook is registered |
| State file age | Generated at in test-state.md | ✅ up to 30 days; ⚠️ 31 to 60 days (/qf-update or /qf-init); ❌ over 60 days (/qf-init) |
| Plugin version | test-state.md against the plugin | ⚠️ when they differ (/qf-init) |
| File counts | each framework's test files, counted again | ⚠️ when they drift by more than 10 % and more than 5 files (/qf-update); ❌ when none remain of a stored count above 0 (/qf-init) |
| Framework tooling | the version command of jest or Vitest, mocha, playwright, cypress, golang, python, rspec, phpunit, junit and cucumber | ⚠️ when the tool isn't found; other slugs are skipped |
Example report:
Setup
CLI ✅ qf <version>
Auth (<identifier>) ⚠️ not configured
State file age ✅ 12 day(s) old
File counts
jest ✅ 47 live (stored: 42)
Framework tooling
jest tooling ✅ <version>
Overall: 1 warning(s), 0 error(s)
Suggested fixes:
qf login <identifier>/qf-update
/qf-update counts each framework's test files again and updates File count and Generated at in test-state.md. It doesn't detect frameworks again; /qf-init does.
/qf-state
/qf-state shows the detected frameworks with live test-file counts, the coverage nudge setting, and whether each identifier is logged in (configured).
/qf-hook
/qf-hook on (or yes) turns the coverage nudge on, and /qf-hook off (or no) turns it off; either creates .qualflare/config.json when it is missing. With no argument, /qf-hook prints the current setting, or says the hook is not configured when there is no config.json.
The coverage nudge (Stop hook)
The plugin registers a Claude Code Stop hook, which runs each time Claude finishes a response, not only at the end of a session. When stopHookEnabled is true in .qualflare/config.json, it reads the session transcript and prints one line when all three conditions below hold:
🔍 Qualflare: 3 source file(s) changed without test updates. Run /qf-cover to add coverage.When the nudge appears
- At least one source file was edited (
.js,.ts,.go,.py,.rb,.php,.rs,.java,.kt, and their JSX and module variants (.jsx,.tsx,.mjs,.cjs,.mts,.cts)). - No test files were edited in the same session.
- At least one of those edits is substantive. An edit made with the Edit tool is trivial, and ignored, when its old and new text are each a single line and their lengths differ by 40 characters or fewer. Whole-file writes (Write) and multi-edits (MultiEdit) always count.
What the hook ignores
| Excluded category | Files |
|---|---|
| Test files | .test. and .spec. files with a js, ts, jsx, tsx, mjs, cjs, mts or cts extension; *_test.go; test_*.py; *_test.py; *_spec.rb under spec/; *Test.php under tests/; and any file under __tests__/, e2e/, cypress/ or playwright/ |
| Config files | *.config. js, ts, jsx, tsx, mjs, cjs, mts, cts or json (for example vite.config.ts); .<name>rc. js, ts, mjs, cjs, mts, cts, json, yaml or yml (for example .eslintrc.json); the bare .eslintrc, .prettierrc, .babelrc, .stylelintrc and .commitlintrc; tsconfig.json and tsconfig.<name>.json |
| Type-only files | *.d.ts, *.d.mts, *.d.cts, types.ts, types.tsx, *.types.ts, *.types.tsx |
| Build and dependency folders | node_modules/, vendor/, .git/, dist/, build/, .next/, __pycache__/, .cache/ |
Toggling
/qf-hook on — enable the nudge
/qf-hook off — disable the nudge
/qf-hook — print current statusState files
/qf-init creates a .qualflare/ directory in the project root:
.qualflare/
├── test-state.md — framework + file-count context (commit this)
├── config.json — hook preference (commit this)
└── results/ — raw test-runner output uploaded by qf <identifier> collect (gitignore this)Add .qualflare/results/ to your .gitignore. The other two files should be committed — they give every session the context it needs without re-running setup.
test-state.md structure
Generated by /qf-init, updated by /qf-update. Contains:
- Project — name, languages, generation timestamp, plugin version
- Packages — path and CLI identifier for each package (one row per package;
(root)for single-package projects) - Frameworks in use — slug, language, file count, and top-level paths per (package, framework) pair
- Frameworks suggested — frameworks detected as possible but not yet installed
- Conventions — test naming pattern and coverage threshold
- Notes — free-text notes from setup
config.json fields
| Field | Type | Description |
|---|---|---|
version | number | Schema version (currently 1) |
stopHookEnabled | boolean | Whether the coverage nudge is active |
Authentication
The plugin uses the same identifier-based auth as the Qualflare CLI. After /qf-init prints your identifiers, register each one in your own terminal, not in Claude Code:
qf login <identifier>qf login asks for the token at a hidden prompt. Don't paste a token into the chat or pass it as an argument. In CI, set QF_TOKEN and run qf login <identifier> --force.
In a monorepo, each package gets its own identifier — run qf login once per package. The CLI saves tokens in qualflare/config.toml under your user config directory: $XDG_CONFIG_HOME, or ~/.config when it is unset, on Linux, ~/Library/Application Support on macOS, %AppData% on Windows. The file is readable only by you (mode 0600). Create tokens in Project Settings > Access Tokens (https://app.qualflare.com/project/<project-identifier>/settings/access-tokens). Creating one: Editor+ · project (requires the Editor role or higher in the project).
Run qf projects to list currently registered identifiers. For the full CLI authentication reference, see Configuration.
Supported frameworks
The plugin uploads through the Qualflare CLI and knows the format slugs below. It doesn't know allure: upload an Allure results directory yourself with qf <identifier> collect allure-results/ qf ≥ 0.4.0 (requires qf 0.4.0 or later) (see Allure results).
| Category | Frameworks |
|---|---|
| Generic (JUnit-compatible) | junit, ctrf, qualflare-json |
| Unit Testing | python (pytest), golang, jest, vitest, mocha, rspec, phpunit, testng |
| BDD | cucumber, karate |
| UI / E2E / Mobile | playwright, cypress, selenium, testcafe, maestro, xctest, espresso, detox, webdriverio, appium, flutter |
| API Testing | newman, k6 |
| Security Testing | zap, trivy, snyk, sonarqube |
/qf-run lists the slugs it runs itself. For any other slug, produce the report with your own tooling, then upload it with /qf-run <report-path> <slug>.
/qf-init records Vitest projects under the jest slug, so /qf-run uploads them as jest. Use --format vitest only when you run qf <identifier> collect yourself. Multi-framework monorepos are supported — /qf-init detects each workspace and tracks them separately.
Upload errors
/qf-run handles each upload by the CLI's exit code:
| Exit code | Meaning | What /qf-run does |
|---|---|---|
| 0 | Uploaded | Records it |
| 3 | Token rejected (401) | Asks you to run qf login <identifier> again; skips that identifier's other uploads |
| 4 | Access denied or plan limit (402, 403) | Records the error |
| 5 | Not found (404) | Records the error |
| 7 | Rate limit or server error (429, 5xx) | Retries once, then records the error |
| 1 | Anything else, including an environment the project doesn't have | Records the error; stops as a missing login on Error: no identifier |
Limits
- Identifier:
^[a-z0-9][a-z0-9_-]{0,62}$(/qf-init). /qf-cover: 2 to 5 cases per function; 8 files per round with--allor no tests yet./qf-fix: one pass and one re-run.- Coverage nudge: needs Node.js; the hook times out after 30 seconds.
Related
- Guides: Claude Code plugin · Quo agent
- Reference: Collect command · Configuration · Environments
- CLI and API: CLI · Installation · Access tokens · CLI troubleshooting
Claude Code plugin
Install the Qualflare plugin for Claude Code, run /qf-init once, then generate tests, run your suite, upload results and fix failures from the chat.
AI Features settings and limits
Qualflare AI usage limits by plan: Quo messages per day and month, monthly launch and case analyses, failure clusters held, resets and the project AI switch.