The agent asked to read the file. Veil decided what happens next.
Data exfiltration guard for AI coding agents.
A high-performance Claude Code hook that blocks direct sensitive-file reads into the agent context and steers operators toward authorized local processing tools, enforcing a clean boundary between orchestration and data access.
veil is the preventive companion to airlock:
veilblocks raw sensitive data from entering the agent context in the first placeairlockproves what derived artifacts later crossed the model boundary
AI coding agents can read any file on your machine. When orchestrating data pipelines on sensitive documents, the agent might cat a file, use the Read tool, or grep through contents — pulling private data into the prompt, which gets sent to the inference API. This violates zero-retention policies and exposes confidential information.
veil intercepts direct file access attempts before they execute, blocking reads
of sensitive files while allowing authorized processing through spine tools
(shape, rvl, profile, canon, etc.) that run as subprocesses and
produce structured metadata — never raw data.
If a downstream workflow later sends derived telemetry to a model, veil is
not the proof layer for that step. airlock owns that boundary attestation.
ALLOW: shape client_data.csv → subprocess, output is schema report
BLOCK: cat client_data.csv → raw data would enter prompt
BLOCK: Read tool on client_data.csv → raw data would enter prompt
ALLOW: Read tool on shape-report.json → derived artifact, safe
Homebrew:
brew tap cmdrvl/tap
brew install cmdrvl/tap/veilInstaller script:
curl -fsSL https://raw.githubusercontent.com/cmdrvl/veil/main/install.sh | bashOr build from source:
cargo install --path .Tagged v* releases build the four supported tarballs, publish
veil-<tag>-SHA256SUMS, then update cmdrvl/homebrew-tap from that published
checksum asset. Configure HOMEBREW_TAP_TOKEN with write access to the tap
repository before cutting a release. The tap job validates Formula/veil.rb,
pushes directly to main when allowed, and opens a documented tap PR if branch
protection blocks the direct push.
The remaining signed checksum/provenance/SBOM release artifact expansion is
tracked separately in bead bd-37f.
veil hooks into Claude Code's PreToolUse event for multiple tool types:
| Hook Matcher | What It Guards |
|---|---|
Read |
Direct file reads into context |
Grep |
Content-mode grep exposing file contents |
Bash |
Common shell-reader patterns that would expose file contents directly |
Treat veil as an operator-first guardrail: it blocks direct reads, then points
you to the configured authorized path for sensitive-file work instead of
encouraging ad hoc shell commands.
# .veil.toml (project root) or ~/.cmdrvl/config/veil/config.toml
[sensitivity]
# Paths that are sensitive (glob patterns)
protected = [
"data/clients/**",
"filings/**/*.xml",
"*.nport.xml",
"exports/*.csv",
]
[spine]
# Spine tools allowed to process sensitive files as subprocesses
authorized_tools = [
"shape", "rvl", "vacuum", "hashbytes",
"fingerprint", "profile", "canon", "lock", "pack",
]
[allowlist]
# Files always safe to read
safe_patterns = [
"*.md", "*.toml", "*.lock",
"docs/**", "tests/**", ".github/**",
"*-report.json", "*-report.yaml",
"package.json", "tsconfig.json",
"Cargo.toml", "Cargo.lock",
]
# NOTE: *.json and *.yaml are NOT safe by default.
# Files like credentials.json, secrets.yaml, service-account.json
# are common sensitive targets. Allowlist specific filenames instead.
[policy]
# What to do when veil detects a sensitive access
# (either a classified-sensitive file anywhere, or any unknown file inside an
# explicitly protected directory)
default = "deny" # deny | warn | log
audit_log = true # Log all access attempts
audit_path = "~/.cmdrvl/logs/veil/audit.jsonl" # default; outside repoveil also ships a built-in CMD+RVL config-protection profile. Direct content
reads under the canonical ~/.cmdrvl/ config and secret-bearing subtrees are
denied by default, including config/, secrets/, guard receipts, Gmail watch
state, holon doctor runs, receipts, migration records, and deprecation notices.
That profile is preserved when user, project, or environment protected patterns
are supplied.
veil configuration intentionally contains no secret-valued fields. Do not put
API keys, tokens, or cloud secret references in veil config files; unknown
sections such as [secrets] are rejected instead of ignored. Because veil
does not require config-file secrets, it does not need an AWS Secrets Manager
or SSM Parameter Store adapter.
When veil blocks a direct read, use the configured authorized path instead of guessing:
veil --robot-triage
veil capabilities --json
veil robot-docs guide
veil operator
veil operator --jsonveil --robot-triage is the fastest read-only machine entrypoint. It returns
doctor health, recommendations, and the capabilities contract in one JSON
document. veil capabilities --json exposes the stable command contract, exit
codes, hook-mode expectations, and composition boundaries. veil robot-docs guide prints the agent-facing quick guide.
veil operator reads [spine] authorized_tools from the active config, runs
--describe on each installed tool, and prints a combined reference with any
missing or broken tools called out explicitly.
veil doctor is read-only. It inspects local configuration, the audit path, and
managed Claude Read/Grep/Bash hook state without installing hooks, rewriting
settings, appending audit records, or using the network.
veil --robot-triage
veil capabilities --json
veil robot-docs guide
veil doctor health
veil doctor health --json
veil doctor capabilities --json
veil doctor robot-docs
veil doctor --robot-triageNo doctor --fix mode is available yet. Any future repair mode must ship with
detector, backup, inverse, fixture, and undo coverage before it is exposed.
Bare veil remains hook mode for Claude/Gemini/Copilot settings and expects a
hook payload on stdin. For operator discovery, use veil --help or the robot
surfaces above instead of running bare veil.
When a sensitive-file read is blocked:
- Run
veil operator. - Pick the authorized spine tool that matches the job.
- Produce metadata or other derived artifacts through that tool instead of reaching for a direct read.
- If those derived artifacts later go to a model, use
airlockto attest the model boundary.
File access attempt (Read/Grep/Bash)
│
├── Allowlist check → safe pattern? → ALLOW (silent)
│
├── Protected-dir / sensitivity check
│ │
│ ├── Is this a spine tool subprocess? → ALLOW (audit log)
│ │
│ └── Direct read into context? → policy default (deny|warn|log)
│
└── Unknown file outside protected dirs → ALLOW
- Unknown file outside
[sensitivity] protecteddirectories is allowed. - Unknown file inside a protected directory is treated as sensitive and resolved through
[policy] default. - Classified-sensitive file anywhere is resolved through pack-specific rules or
[policy] default, with direct reads denied by default. - Operator/domain commands fail closed unless the active Claude
PreToolUsesettings contain healthyveilRead/Grep/Bash hooks and a healthydcgBash hook.veil doctor,veil install, andveil uninstallremain available as guard-maintenance commands when the preflight is failing.
| Tool | Role |
|---|---|
| dcg | Blocks destructive commands (git reset, rm -rf) |
| veil | Blocks data exfiltration (reading sensitive files) |
| airlock | Proves what derived artifacts crossed the model boundary |
| post-compact-reminder | Re-reads AGENTS.md after context compaction |
| spine tools | Authorized processing path for sensitive data |
veil is modeled after dcg and shares key architectural patterns:
- Layered configuration: project > user > system > defaults
- Fail-safe design: budget exceeded → allow with audit log
- Sub-millisecond latency: fast-path glob matching with early exit
- Multi-protocol support: Claude Code, Gemini CLI, Copilot
- Rich denial output: explains why, suggests alternatives
- Audit trail: every access attempt logged with timestamps
veil and airlock are complementary, not competitive.
raw sensitive files
-> veil / local read guard
-> authorized spine subprocesses
-> derived telemetry artifacts
-> airlock assemble / verify
-> model request
veilis a host-side prevention tool. It decides whether the agent may read a file or invoke a shell command that would expose raw contents.airlockis a model-boundary proof tool. It decides what claim can be made about the exact prompt and request bytes that crossed to a model.veildoes not emit boundary manifests or prove model cleanliness.airlockdoes not stop a local agent fromcat-ing a file before prompt assembly.
That split matters. veil protects the local working environment. airlock
attests the model boundary.
veil is a path guard, not an outbound disclosure policy engine.
It can decide whether an agent may read a local path, grep file contents, or run a shell reader that would expose raw sensitive bytes. It can also help wrappers preflight attachment paths before send-time workflows hand those files to an email or chat client.
It does not decide whether an outbound message body is safe, complete, appropriate for a counterpart, or compliant with a relationship-specific disclosure profile. That belongs in the calling wrapper and, later, the KOVREX surface that owns counterpart identity, authorization, approval state, and send-path policy.
Use the split this way:
veil: block raw local reads and screen referenced file paths.- calling wrapper: classify outbound intent, recipient, approval context, and body text.
- KOVREX integration: enforce account, counterpart, and disclosure policy before a send action is allowed.
Do not extend veil into a generic outbound content moderator. If the outbound
body is already in the agent context, veil is no longer the right abstraction.
Agent orchestrates spine tools directly. veil blocks direct file reads. Spine
tool output is redacted by default (--explicit to show raw values). If any
derived telemetry later goes to a model, pair this with airlock for boundary
proof. Good for most sensitivity levels.
Agent never touches documents. It writes a deterministic pipeline script that the client deploys on their own machine. Claude's job ends at code generation. No veil needed — the agent never runs on the same machine as the data.
MIT
veil is part of the open-source toolchain from the CMD+RVL lineage and AI enablement practice. MIT-licensed. Contributions welcome from any practice or stack.
