Debugging & troubleshooting

Most issues come down to one of three things: the machine isn't connected, it hasn't synced a bundle yet, or the hook isn't wired correctly. This page maps the exact message you'll see to its fix. Start by running skillsvault status — it shows the connected org, the bundle version, and how long ago it synced.

Quick reference

SymptomCauseFix
not configured — run skillsvault loginNo credentials on this machineskillsvault login (or skillsvault configure for CI)
no bundle — run skillsvault syncConnected but never syncedskillsvault sync
REJECTED bundle: signature verification failedPinned org key no longer matchesReconnect to re-pin: skillsvault login
Gate exits 2 unexpectedlySkill is banned or non-compliantCheck skillsvault status and your policies
Hook never blocks in Claude CodeMatcher wrong / not syncedMatcher must be "Skill"; run skillsvault sync
HTTP 401Bad or missing agent keyCheck the key in Settings → Agent keys
HTTP 403Key used against another orgUse the key's own org slug
no harnesses detected on this machinepull found no known agent dirsPass --harness <h> or --dir <path>

Connection & sync

not configured

The CLI keeps per-machine state under ~/.skillsvault. If it's missing you'll see not configured — run skillsvault login. Connect interactively with skillsvault login, or non-interactively (CI) with skillsvault configure --org <slug> --key <agent-key> --url <base>.

no bundle — run skillsvault sync

The gate decides from a locally-synced bundle. A freshly connected machine has none until you run skillsvault sync, which pulls and verifies it. Confirm with skillsvault status:

skillsvault status
# bundle    v1750848000 · 4 skills · 3 policies
# synced    2m ago

REJECTED bundle: signature verification failed

On connect, the CLI pins your org's signing key and then refuses any bundle that doesn't verify against it. If the org's key was rotated, an old pin will reject the new bundle. Reconnect to re-pin the current key:

skillsvault login        # re-pins the org's current signing key
skillsvault sync

The last-good bundle is kept on a rejected sync, so the gate keeps working on the previous policy until you re-pin.

Enforcement

Gate exits 2 when you didn't expect it

Exit 2 is a halt. It means the skill is banned, or it sits under a managed namespace without a valid current manifest (the "managed missing manifest" default). Inspect the synced bundle with skillsvault status and review the matching rule in Policies. To see the decision and reason directly:

skillsvault gate --skill acme/teamleader-crm-entry
# ⛔ HALT acme/teamleader-crm-entry
#    policy: Teamleader retired
#    Use acme/hubspot-crm-entry instead.

The Claude Code hook isn't blocking

Three things to check, in order:

  1. The matcher is "Skill". Print the correct config with skillsvault install-hook and paste it into .claude/settings.json. See Harness coverage.
  2. A bundle is synced. Run skillsvault sync first — with no bundle the gate can't decide.
  3. You're reading the right signal. In hook mode the gate always exits 0 and signals a block via permissionDecision: "deny" in its JSON output — not via the exit code. That's by design; see The runtime gate.

Enforcement is cooperative

The gate stops the accidental run of a stale or banned skill. It does not stop a developer who removes the hook or sideloads a folder outside a managed namespace. If a banned skill still runs, confirm the hook is installed and the namespace is managed.

API errors

When using the REST API or skillsvault against a remote control plane:

  • 401 — the agent key is missing or unknown. Confirm the X-Skillsvault-Key (or Authorization: Bearer) header and that the key still exists in Settings → Agent keys.
  • 403 — the key is valid but you're calling a different org's path than the key belongs to. Use the key's own org slug.

Offline & staleness

The gate never needs the network to decide — it uses the last-good bundle on disk, so an offline laptop keeps enforcing. If that bundle is older than the org's staleness threshold, the gate escalates: a stale bundle can turn an allow into a warn or halt (it only ever becomes more restrictive). Reconnect and skillsvault sync to refresh.

Inspecting state

skillsvault status              # org, bundle version, sync age
skillsvault status --json       # machine-readable, for scripts
skillsvault detect              # AI agents found, enforced vs distribution-only
skillsvault gate --skill <name> # dry-run a decision with full reason

Add --no-color (or set NO_COLOR=1 / TERM=dumb) when capturing output, so logs and pipes stay plain text.