QG
QualityGraph
CLI/Documentation
Install

CLI Documentation

Complete guide to installing, configuring, and using the QualityGraph CLI to analyze test coverage across your repositories.

Installation

Prerequisites

  • Node.js 18+ — check with node -v
  • macOS or Linux — Windows support via WSL
  • Git — your project must be a git repository

One-liner install

bash
curl -fsSL https://qualitygraph.harnessqa.dev/cli-dist/install.sh | bash

This downloads the CLI bundle and installs it to ~/.qualitygraph/bin/qg. It also adds the directory to your PATH in your shell config.

After installation

Reload your shell or source your config to use qg immediately:

terminal
source ~/.zshrc    # or ~/.bashrc

Verify it works:

terminal
qg --version

Manual install

If you prefer not to pipe curl to bash:

bash
# Download the bundle
curl -o ~/.qualitygraph/bin/qg-bundle.js https://qualitygraph.harnessqa.dev/cli-dist/qg-bundle.js
mkdir -p ~/.qualitygraph/bin

# Create wrapper script
cat > ~/.qualitygraph/bin/qg <<'EOF'
#!/usr/bin/env node
require('./qg-bundle.js');
EOF
chmod +x ~/.qualitygraph/bin/qg

# Add to PATH
export PATH="$HOME/.qualitygraph/bin:$PATH"

Uninstall

bash
rm -rf ~/.qualitygraph
# Then remove the PATH line from your ~/.zshrc or ~/.bashrc

Authentication

You need a QualityGraph account to upload analysis results. Create one at qualitygraph.harnessqa.dev/login or use the login command directly (it will register you automatically if you don't have an account).

Login

terminal
qg login -e you@company.com -p your-password

Check status

terminal
qg status
Logged in as: you@company.com
Server: https://qualitygraph.harnessqa.dev

Logout

terminal
qg logout

Security: Your credentials are stored locally at ~/.qualitygraph/config.json with file permissions 0600 (owner read/write only). The JWT token expires after 7 days — re-run qg login to refresh.

Analyzing Repositories

Basic usage

Navigate to any git repository and run:

terminal
cd /path/to/your/project
qg analyze

The CLI does two things. It scans the source tree, identifies test files, classifies them by layer (unit, API, integration, UI, E2E, contract) and estimates which production files have a test. And it looks for coverage reports a test run left behind (coverage/lcov.info, coverage.xml, jacoco.xml) and uploads those as measured coverage, with per-file and per-line detail. A measurement always outranks the estimate for its layer.

Example output

$ qg analyze

Analyzing myorg/backend-api...

Scanned 1,204 files

  myorg/backend-api
  ────────────────────────────────────────────────────────────
  Test Type       Coverage   Files        Test Files   Lines
  ────────────────────────────────────────────────────────────
  UNIT            42.30% [████░░░░░░]   89/ 210       94     18240/ 43120
  API              8.10% [█░░░░░░░░░]   17/ 210       12      3499/ 43120
  INTEGRATION      3.33% [░░░░░░░░░░]    7/ 210        5      1438/ 43120
  E2E              1.90% [░░░░░░░░░░]    4/ 210        8       820/ 43120
  ────────────────────────────────────────────────────────────

  Coverage reports found (1):
    lcov      coverage/lcov.info  (184.2 KB)
  These measure what the tests ran; they replace the file-layout estimate for their layer.

Uploading to https://qualitygraph.harnessqa.dev...
Uploaded! Repository: a1b2c3d4-...
View at: https://qualitygraph.harnessqa.dev
Uploading coverage/lcov.info as UNIT coverage (lcov)... 71.4% of 43120 lines, 210 files

Run the tests first

The measured numbers come from your own test runner, so run it with coverage on before qg analyze:

terminal
npx jest --coverage                 # writes coverage/lcov.info
pytest --cov=src --cov-report=xml   # writes coverage.xml
./gradlew test jacocoTestReport     # writes build/reports/jacoco/test/jacocoTestReport.xml
qg analyze

Reports are filed under the layer given by --report-type (default UNIT). To upload a specific file, or reports for several layers, use qg coverage upload:

terminal
qg coverage upload coverage/lcov.info --type UNIT
qg coverage upload reports/api-coverage.xml --type API --format cobertura
qg analyze --no-reports             # estimate only, skip report discovery

Local-only mode

Run the analysis without uploading results — useful for previewing before pushing, or for repos you don't want tracked:

terminal
qg analyze --local

Analyze a different directory

terminal
qg analyze -d /path/to/other-repo

How the estimate is calculated

Without a report, QualityGraph falls back to structural file-based analysis, shown as an estimate in the dashboard. It works by:

  1. Scanning all source files in the repository (skipping node_modules, dist, etc.)
  2. Identifying test files by naming convention and directory patterns
  3. Classifying each test file into a test type (unit, API, integration, etc.)
  4. Matching test files to production files by name and by mirrored layout (user.test.ts → user.ts, src/test/kotlin/…/FooTest.kt → src/main/kotlin/…/Foo.kt, spec/models/user_spec.rb → app/models/user.rb)
  5. Calculating the ratio of production files that have a matching test file, with real line counts from the checkout

IDE scaffolding such as ExampleUnitTest and test helpers under tests/fixtures are not counted as tests. The estimate is language-agnostic and needs no build step, but it only says which files have a test, not which lines ran. Upload a report to get the real number.

Command Reference

CommandDescriptionOptions
qg loginAuthenticate with QualityGraph-e, --email (required)
-p, --password (required)
-s, --server (custom server URL)
qg analyzeScan repo and upload results-d, --dir (repo path, default: .)
--local (skip upload)
qg coverage upload <file...>Upload lcov.info, Cobertura or JaCoCo reports from a test run as measured coverage. Options: --type (layer, default UNIT), --format, --branch, --dir-d, --dir (repo path, default: .)
--local (skip upload)
qg statusShow current login statusnone
qg logoutClear stored credentialsnone
qg --versionShow CLI versionnone
qg --helpShow helpnone

Test Detection

The CLI identifies test files by their naming conventions and directory structure, then classifies them into five test types:

Unit TestsUNIT

Default classification. Any test file that doesn't match a more specific pattern.

File patterns

.test.ts.test.js.spec.ts.spec.js_test.go_test.pytest_*.pyTest.javaSpec.java_test.rb_spec.rbTest.ktTests.csTests.swiftTest.php

Directory patterns

__tests__/tests/test/spec/
API TestsAPI

Tests that validate HTTP endpoints and API contracts.

File patterns

.api.test.ts.api.spec.ts.api.test.js

Directory patterns

api-tests/api/tests/api/test/
Integration TestsINTEGRATION

Tests that verify interactions between multiple components or services.

File patterns

.integration.test.ts.integration.spec.ts.int.test.ts.int.spec.ts

Directory patterns

integration/
E2E TestsE2E

End-to-end tests using browser automation frameworks.

File patterns

.e2e.ts.e2e.js.e2e-spec.ts

Directory patterns

e2e/cypress/playwright/
Contract TestsCONTRACT

Consumer-driven contract tests (Pact, etc.).

File patterns

.contract.test.ts.contract.spec.ts.pact.test.ts.pact.spec.ts

Directory patterns

contract/pact/

Ignored paths: The following are always excluded from analysis: node_modules/, dist/, build/, .git/, vendor/, coverage/, plus config files, lock files, assets, stylesheets, and documentation.

Supported Languages

The CLI recognizes source and test files in the following languages:

TypeScript

.ts, .tsx

JavaScript

.js, .jsx

Python

.py

Go

.go

Java

.java

Kotlin

.kt

Ruby

.rb

Rust

.rs

C#

.cs

Swift

.swift

PHP

.php

C/C++

.c, .cpp, .h

Configuration

All CLI configuration is stored in ~/.qualitygraph/config.json.

Config file format

{
  "server": "https://qualitygraph.harnessqa.dev",
  "token": "eyJhbGciOiJIUzI1NiIs...",
  "email": "you@company.com"
}

File structure

~/.qualitygraph/
├── bin/
│   ├── qg              # CLI wrapper script
│   └── qg-bundle.js    # Bundled CLI (122KB)
└── config.json          # Auth credentials (mode 0600)

Custom server

For self-hosted QualityGraph instances, pass the -s flag:

terminal
qg login -e you@company.com -p pass -s https://qg.internal.company.com

CI/CD Integration

Run QualityGraph analysis automatically in your CI pipeline to track coverage over time.

GitHub Actions

name: QualityGraph Analysis

on:
  push:
    branches: [main]
  pull_request:

jobs:
  analyze:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '20'

      - name: Install QualityGraph CLI
        run: curl -fsSL https://qualitygraph.harnessqa.dev/cli-dist/install.sh | bash

      - name: Login & analyze
        run: |
          export PATH="$HOME/.qualitygraph/bin:$PATH"
          qg login -e ${{ secrets.QG_EMAIL }} -p ${{ secrets.QG_PASSWORD }}
          qg analyze

Tip: Store your QualityGraph credentials as repository secrets (QG_EMAIL and QG_PASSWORD) to keep them secure.

GitLab CI

qualitygraph:
  image: node:20
  stage: test
  script:
    - curl -fsSL https://qualitygraph.harnessqa.dev/cli-dist/install.sh | bash
    - export PATH="$HOME/.qualitygraph/bin:$PATH"
    - qg login -e $QG_EMAIL -p $QG_PASSWORD
    - qg analyze
  only:
    - main

Troubleshooting

qg: command not found

Your PATH hasn't been updated yet. Either open a new terminal or run:

terminal
source ~/.zshrc    # or ~/.bashrc

Not a git repository

The CLI must be run inside a git repo. Make sure you're in the project root, or use the -d flag:

terminal
qg analyze -d /path/to/repo

Session expired

JWT tokens expire after 7 days. Re-authenticate:

terminal
qg login -e you@company.com -p your-password

No test files detected

The analyzer may not recognize your test naming convention. Check that your test files follow standard patterns like .test.ts, .spec.js, _test.go, etc. Run with --local to preview what's detected.

terminal
qg analyze --local

Upload failed: HTTP 401

Your token is invalid or expired. Log in again:

terminal
qg login -e you@company.com -p your-password

FAQ

Does the CLI upload my source code?

No. The CLI only uploads file paths and sizes — no file contents, no code, no secrets. The analysis is performed entirely on your machine.

Can I use GitHub OAuth instead of email/password?

The CLI currently supports email/password authentication. You can link your GitHub account by signing in on the web dashboard first, then using the same email for the CLI.

What's the difference between this and code coverage tools like Istanbul or Codecov?

Traditional code coverage measures which lines of code are executed during tests (runtime analysis). QualityGraph measures structural test coverage — which production files have corresponding test files, across all test types. This gives a higher-level view of your test strategy across repositories.

Can I use this with monorepos?

Yes. Run qg analyze from the monorepo root and it will scan all subdirectories. The analyzer respects standard ignore patterns (node_modules, dist, build).

How often should I run the analysis?

We recommend running it on every push to main via CI/CD. This gives you a continuous view of how your test coverage evolves over time.

QualityGraph CLI v0.1.0 — Cross-repository QA intelligence. Install · REST API · Sign in · Pricing