Batch Signing Guide

Sign entire build directories with glob patterns, parallel workers, auto-verification, and resume-on-failure. All files share a single credential session.

Quick start

npm install -g @qwickcert/cli
qwick auth login
qwick sign "dist/**/*.exe" --verify

This signs every .exe file in dist/ recursively and verifies each signature afterward.

File patterns

The CLI uses fast-glob for pattern matching, supporting recursive globs, brace expansion, and negation.

Recursive globs

qwick sign "dist/**/*.exe"        # all .exe in dist/ and subdirectories
qwick sign "build/**/*.dll"       # all .dll in build/ tree

Brace expansion

qwick sign "dist/**/*.{exe,dll,msi}"   # multiple extensions

Exclude patterns

Use excludePatterns in your .qwickrc.json to skip files by pattern:

{
  "files": ["dist/**/*.exe"],
  "excludePatterns": ["*test*", "*debug*"]
}

Project configuration (.qwickrc.json)

Store all signing settings in a config file so your team can run qwick sign with no arguments.

qwick config init
{
  "project": "my-app",
  "organization": "acme-corp",
  "files": ["dist/**/*.exe", "dist/**/*.dll"],
  "excludePatterns": ["*test*"],
  "timestampUrl": "http://timestamp.acs.microsoft.com",
  "digestAlgorithm": "sha256",
  "parallel": 4,
  "verify": true,
  "outputFormat": "text"
}

See the CLI Reference for the full schema and precedence order.

Parallel signing

Run multiple SignTool processes concurrently to speed up large batch jobs. All workers share the same credential session.

qwick sign "dist/**/*.exe" --parallel 4

Worker count recommendations

  • 1-5 files: --parallel 1 (default, no overhead)
  • 5-20 files: --parallel 2-4
  • 20+ files: --parallel 4-8
  • Maximum: --parallel 16

Auto-verify

The --verify flag runs signtool verify /pa on every signed file. If any verification fails, the CLI exits with a non-zero code.

qwick sign "dist/**/*.exe" --verify

# Output:
# ✓ Signed 12 files in 18.4s — all signatures verified

You can also enable this permanently in .qwickrc.json:

{ "verify": true }

Resume on failure

If signing is interrupted (crash, network error, Ctrl+C), the CLI saves progress to .qwick-signing-state.json. Resume where you left off:

# First attempt — interrupted after 5/20 files
qwick sign "dist/**/*.exe" --progress

# Resume — skips the 5 already-signed files
qwick sign "dist/**/*.exe" --resume

Don't forget your .gitignore

Add .qwick-signing-state.json to your .gitignore — it's a temporary file that should not be committed.

CI/CD integration

Use --output json for machine-readable output in CI pipelines. The exit code is the canonical success/failure signal.

qwick sign "dist/**/*.exe" --output json --verify

The JSON output includes per-file results, timing, the operation ID, and verification status.

GitHub Actions example

- name: Sign build output
  run: |
    npx @qwickcert/cli sign "dist/**/*.{exe,dll}" \
      --parallel 4 \
      --verify \
      --output json > signing-results.json
  env:
    QWICK_API_KEY: ${{ secrets.QWICK_API_KEY }}
    QWICK_PROJECT: my-app

Best practices

Mind the credential TTL

Signing credentials expire after 10 minutes. For very large batches (100+ files), use --parallel 8 or higher to stay within the window.

Add temp files to .gitignore

Add .qwick-signing-state.json to your .gitignore.

Always use --verify in CI

The --verify flag catches silent failures. Make it a default in your .qwickrc.json.

Quote glob patterns in your shell

Always wrap glob patterns in quotes ("dist/**/*.exe") to prevent your shell from expanding them before the CLI sees them.