Skip to main content

kyvvu-claude

Kyvvu agent-security integration for Claude Code. Evaluates every tool call against Kyvvu policies before execution via Claude Code's native hook system - stopping credential leakage and destructive commands - and records all tool calls as an audit trail (the platform hash-chains it on ingestion when the trace goes there).

Installation

pip install kyvvu-claude

Requires Python 3.10+ and macOS or Linux.

Getting started

1. Create a Kyvvu account

Sign up at platform.kyvvu.com and create an API key from your organization settings. The API key starts with KvKey-.

2. Initialize kyvvu-claude

kyvvu-claude init

This interactive wizard will:

  • Connect to the Kyvvu API (defaults to https://platform.kyvvu.com)
  • Register your Claude Code instance as a Kyvvu agent
  • Fetch policies assigned to your agent
  • Install hooks into Claude Code's ~/.claude/settings.json

3. Start using Claude Code

That's it. All Claude Code tool calls are now evaluated before they run. Open the Kyvvu dashboard to see your agent's behavioral traces.

4. (Optional) Assign policies

In the Kyvvu dashboard, assign a manifest to your Claude Code agent. We recommend starting with the Claude Code Safety manifest (manifests/developer/claude-code-safety.yaml) which protects against:

  • Credential exfiltration (blocks Bash after reading .env, .pem, .key files)
  • Destructive commands (git push --force, rm -rf /, git reset --hard)
  • Scope escape (writes to /etc, ~/.ssh, ~/.aws)
  • Runaway loops (max 50 Bash calls, max 10 consecutive)
  • PII in commands (SSN, credit card patterns)

How it works

kyvvu-claude uses Claude Code's hook system. Each hook invocation is a fresh process that reads JSON from stdin and writes JSON to stdout.

Claude Code                          kyvvu-claude
    |                                     |
    +-- SessionStart --stdin JSON--->  Register task, fetch policies from API
    |                                  Return status message
    |
    +-- PreToolUse ----stdin JSON--->  Map tool -> Kyvvu Behavior
    |                                  Evaluate policies (local, <50ms)
    |                                  Block or allow
    |
    +-- PostToolUse ---stdin JSON--->  Record completed step in session history
    |                                  (for path-dependent rules)
    |
    +-- SubagentStart -stdin JSON--->  Link spawned sub-agent to its parent
    |                                  Agent/Task step (back-reference)
    |
    +-- SubagentStop --stdin JSON--->  Record sub-agent boundary in the trail
    |
    +-- SessionEnd ----stdin JSON--->  Flush audit trail to API
                                       Clean up session

Policy evaluation is fully local via kyvvu-engine — no network I/O on the hot path. Policies are fetched from the API at session start and cached on disk.

LLM calls are captured from Claude Code's session transcript (model name, token usage, proposed tools) and included in the behavioral trace.

The audit trail model

The audit trail is a single flat list of steps per task — there is no nesting and no per-sub-agent task_id. Two things define ordering and structure:

  • Ordering is by timestamp. Every step carries a reliable UTC timestamp: tool steps are stamped when the hook records them, and step.model (LLM call) steps reuse the timestamp from Claude Code's transcript so they sort by when the call actually happened. Read the trail in timestamp order.
  • step (the step counter) is a per-task monotonic id and timestamp tiebreaker — not a causality guarantee. It increments as steps are recorded, but Claude Code issues tool calls in parallel batches and sub-agents widen that concurrency, so a higher step does not mean "caused by" a lower one. Do not infer happens-before from step alone; use it only to break ties between equal timestamps and to reference a specific step.

Sub-agent partial order (flat storage, reconstructable)

When Claude Code fans out to sub-agents (the Task/Agent tool), every sub-agent's inner tool calls are merged into the same flat task trail. Flat storage is retained, but enough structure is stamped onto each step that the meaningful partial orders reconstruct without nesting:

  • Each step carries a sub-agent correlation stamp under properties["kyvvu.subagent"]: {"id": <tag>, "depth": <0|1>, "spawn_step": <parent step>}. The tag is "main" for the parent session, or the sub-agent's id derived from its dedicated transcript path (…/subagents/agent-{id}.jsonl).
  • Within one sub-agent: group steps by their kyvvu.subagent.id, then order by timestamp. This keeps a sub-agent's own read-then-exec sequence intact even though a sibling's steps may be interleaved in flat storage.
  • Parent → child: each sub-agent step carries spawn_step, the parent Agent/Task step that spawned it (established from the SubagentStart lifecycle hook). This preserves the platform-guaranteed "read .env, then delegate" happens-before.
  • Cross-sibling order is deliberately not preserved — concurrent siblings are a genuine race, so their relative order is dropped (out of scope per design).

Enforcement is independent of these tags. Policy replay is always whole-task (conservative): at every PreToolUse the engine replays the entire task history regardless of sub-agent lineage, so a secret read in one sub-agent still taints exec anywhere in the task. The sub-agent tags are for storage and reconstruction only — they never scope enforcement.

Enforcement behavior

When a policy blocks a tool call, kyvvu-claude returns permissionDecision: "deny" to Claude Code. This denies the specific tool call but does not stop the agent. Claude Code treats it like a permission denial — the model continues reasoning and may try alternative approaches.

This is intentional and consistent with Claude Code's hook design:

  • The blocked step is recorded in the audit trail with output.status = "blocked"
  • The policy name and severity are logged locally in ~/.kyvvu-claude/session.log
  • An incident is reported to the Kyvvu API
  • The model receives the block reason and adapts

Tainted-path policies (credential exfiltration guard) are permanent within a session: after reading a secret file (.env, .pem, .key, etc.), ALL subsequent Bash commands and file reads outside the project are blocked. Use /clear in Claude Code to start a new session and reset the taint.

Tool mapping

Claude Code Tool Step Type Verb Properties
Bash step.exec - exec.command (+ target.host / data.classification parsed from shell writes & secret reads)
Read step.resource GET target.host (file path)
Write step.resource POST target.host (file path)
Edit step.resource PATCH target.host (file path)
Glob step.resource GET target.host, target.pattern
Grep step.resource GET target.host, target.pattern
WebFetch step.resource GET target.host (URL)
WebSearch step.resource GET target.host (query)
Agent step.self POST target.description
NotebookEdit step.resource PATCH target.host (notebook path)
mcp__* step.resource * target.mcp_server, target.mcp_tool
(unknown) step.unknown - tool_input.*

Files matching secret patterns (.env, .pem, .key, .secret, .credentials, .pgpass, .netrc) are automatically classified with data.classification: secret for tainted-path policies. This applies both to the file tools (Read/Edit/Write/Glob/Grep) and to shell commands: a Bash command that reads a secret file (cat .env, cp *.pem …) is classified too, and a Bash shell write (>, >>, tee, cp, mv, …) sets target.host so scope-containment policies apply to shell writes — not just the Write/Edit tools.

Configuration

Stored at ~/.kyvvu-claude/config.json:

Field Default Description
api_url https://platform.kyvvu.com Kyvvu API URL (policy fetch + agent registration)
log_location auto (follows policy source) WHERE logs go. stdout = local. none = disabled. Can be a URL or file path. auto resolves to the platform when it is the policy source, else stdout.
log_format kv HOW logs are formatted: kv (Kyvvu API), json, or otlp
incident_location (empty = inherit trace sink) WHERE incidents go. Same vocabulary as log_location; empty inherits the trace sink.
incident_format (empty = inherit log_format) HOW incidents are formatted: kv, json, or otlp. Empty inherits log_format.
api_key (required) API key from your Kyvvu organization (KvKey-...)
agent_id (auto) Assigned at registration
enforce false true = block violations, false = observe-only (log but allow)
environment development development, staging, or production
risk_classification limited EU AI Act tier: high, limited, or minimal
flush_threshold 100 Flush logs after N steps (0 = only at session end)
log_full_content false Include full tool input/output in logs

Compatibility

kyvvu-claude uses Claude Code's hook system. It works with:

  • Claude Code CLI (claude command)
  • VS Code extension (Claude Code in VS Code)
  • JetBrains plugin (Claude Code in IntelliJ/PyCharm)
  • GitHub Actions (anthropics/claude-code-action) — reads .claude/settings.json from repo

Not supported: Claude Desktop (macOS/Windows app). Claude Desktop uses MCP servers instead of hooks. Hooks are runtime-invoked (the infrastructure calls them unconditionally on every tool use). MCP tools are model-invoked, so compliance enforcement cannot be guaranteed.

CLI commands

Command Description
kyvvu-claude init Interactive setup: API connection, agent registration, hook installation
kyvvu-claude install-hooks Install hooks into ~/.claude/settings.json (also offered during init)
kyvvu-claude uninstall-hooks Remove kyvvu-claude hooks from Claude Code settings
kyvvu-claude status Show current configuration, policy count, active sessions
kyvvu-claude policies Display cached policies as a table
kyvvu-claude refresh Force policy refresh from the API

Known limitations

  • Tool blocks deny the tool call but do not stop the session — Claude Code continues reasoning and may try alternatives. This is consistent with how Claude Code handles permission denials.
  • LLM calls are observed, not blocked — captured from the session transcript (model name, token usage) but cannot be intercepted pre-flight since no hook fires before model inference.
  • LLM call capture may miss very short sessions — the transcript is written asynchronously by Claude Code; in sessions under ~10 seconds, LLM calls may not appear in the trace.
  • Does not work with Claude Desktop — only Claude Code CLI, IDE extensions, and GitHub Actions.
  • macOS and Linux only — uses fcntl.flock for session file locking (no Windows support).

Uninstalling

kyvvu-claude uninstall-hooks
pip uninstall kyvvu-claude
rm -rf ~/.kyvvu-claude

Metadata

Release files for kyvvu-claude 0.6.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for kyvvu-claude 0.6.0
File Size Uploaded
kyvvu_claude-0.6.0.tar.gz 123.3 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for kyvvu-claude 0.6.0
File Interpreter ABI Platform
kyvvu_claude-0.6.0-py3-none-any.whl Python 3 none any Details

Total release size: 201.5 kB

Release files / kyvvu_claude-0.6.0.tar.gz

Download URL kyvvu_claude-0.6.0.tar.gz
Size 123.3 kB
Tags Source
SHA-256 checksum
How to use checksums
aea01a83af543c52911bdd295b1462a0ccada81ba563a1dad3603cef9c258db2
BLAKE2b-256 checksum
How to use checksums
0e431bf8c53dfd9bbdbd80b5b1a266e75747be44dd4ac31c9c2c1f9fe3906ef6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.5 {"installer":{"name":"uv","version":"0.12.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / kyvvu_claude-0.6.0-py3-none-any.whl

Download URL kyvvu_claude-0.6.0-py3-none-any.whl
Size 78.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
e17a7cf3eb32b9c845011c46e4e7289c9529c92812ebac02adff84130ae5f53b
BLAKE2b-256 checksum
How to use checksums
9d867c5b54867592be4050c3e46649c22bd118063fa760f5b6dba9fd48480e3c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.5 {"installer":{"name":"uv","version":"0.12.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release history Release notifications | RSS feed

This release

0.6.0 This release

2 release files

0.5.2

2 release files

0.5.1

2 release files

0.5.0

2 release files

0.4.0

2 release files

0.3.0

2 release files

0.2.1

2 release files

0.2.0

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page