Coding agents read environment variables, .env files, configuration, and command output that may contain credentials.
ContextVeil locally replaces the secret values you’ve chosen before supported text reaches the LLM — without blocking the workflow.
GITHUB_TOKEN=ghp_secret_example -> GITHUB_TOKEN=<SECRET:GITHUB_TOKEN>
The command still runs. The file still gets read. Only enrolled exact values are replaced; the rest of the output stays intact.
Install the latest stable release:
curl -fsSL https://raw.githubusercontent.com/daniel-sc/contextveil/v1.0.0/install.sh | bash
From your project directory, run:
~/.local/bin/contextveil setup
Review the suggested sources and select your coding-agent integration. Restart
the agent; in Codex, trust the hook on the Hooks need review screen or through
/hooks. Then run ~/.local/bin/contextveil doctor.
Setup requires a terminal and is safe to rerun. Add ~/.local/bin to your PATH
to use the shorter contextveil command.
Imagine asking a coding agent to debug your app. It reads .env or runs a command
such as printenv. Most of the output is useful, but it also contains an API key.
That key may become part of the next request to the model (LLM).
ContextVeil does not block the file read or command. The local operation still happens. On a supported harness integration path, ContextVeil changes the text headed to the model and leaves the rest useful:
DATABASE_URL=postgres://localhost/my_app
API_TOKEN=<SECRET:API_TOKEN>
LOG_LEVEL=debug
This is deliberately a small tool. It is not trying to recognize every possible secret or control everything an agent can do.
contextveil setup does the thoughtful part: it checks bounded known credential
files and probes maintained credential fields, alongside secret-like names and
credential-bearing URLs. These probes may suggest stale or non-secret strings.
New suggestions are automatically selected unless collisions are found; common
configuration literals are omitted. You can also add sources manually. Setup
shows only masked previews, lets you choose what to protect, and installs the
integrations you select. It does not scan arbitrary structured files or keys.
Daily use is boring on purpose: ContextVeil reads the current values, performs local exact-text replacement, and exits. There is no daemon, no network request, no account, no hosted service and no LLM deciding what looks secret. Clean events are silent.
And of course it is fast. You won't notice it, promise!
flowchart TD
subgraph setup [Setup: run once, rerun when needed]
direction LR
A[Find likely environment, .env, and Known Source entries]
B[You choose what to protect]
C[Install selected coding-agent integrations]
D[Store where values live, not the values]
A --> B --> C --> D
end
subgraph persistence [Persistence: configuration files]
direction LR
X[Global<br>~/.config/contextveil/config.toml]
Y[Project<br>.contextveil.toml]
X ~~~ Y
end
subgraph runtime [Runtime: for each supported event]
direction LR
E[Coding agent produces model-bound text]
F[Read current values from enrolled sources]
G{Exact value found?}
H[Pass text through unchanged]
I[Replace value with a placeholder]
J[Cleaned text continues to the LLM]
E --> F --> G
G -- No --> H --> J
G -- Yes --> I --> J
end
setup -. Stored in .-> persistence
persistence -. Used by .-> runtime
ContextVeil stores where to find each value, such as “the API_TOKEN environment
variable,” “the STRIPE_KEY entry in .env.local,” “the exact
/tokens/access_token field in auth.json,” or “the decoded
spring.datasource.password key in application.properties,” or “the exact
//registry.npmjs.org/:_authToken entry in .npmrc.” It does not copy
the value into its configuration. Changes to dotenv, JSON, properties, and npmrc files apply on the next supported
event. Environment changes apply after you restart the coding agent.
During setup, the following shared vocabulary identifies secret-like source names:
| Terms | Whole token | Compact suffix |
|---|---|---|
token, secret, password, passwd, passphrase, credential, credentials | Yes | Yes |
key | Yes | No |
apikey, accesskey, privatekey, clientsecret, authtoken, refreshtoken | No | Yes |
Matching is ASCII case-insensitive: Whole token means the term appears anywhere as a distinct part separated by _, -, ., spaces, or other non-ASCII-alphanumeric characters, such as DB_PASSWORD_PROD.
Compact suffix means those separators are removed and the resulting name ends with the term, such as StripeApiKey; plain key is excluded here to limit false positives.
Automatic suggestions currently cover:
.npmrc, using exact credential keys plus the same general name and URL checks.Across these rules, setup skips automatic suggestions whose
value are common literals, such as true, yes, on, 0,
enabled, null, nil, none, undefined, etc.
See the full Known Source Rule inventory for exact locations, fields, and exclusions.
Environment variables, dotenv files, JSON (including JSON5) files, exact Java properties keys, and exact npmrc keys can also be added manually without matching these automatic discovery rules.
Your agent may install ContextVeil, but source selection stays with you. Ask it to:
~/.local/bin.checksum verified, then run ~/.local/bin/contextveil --version.~/.local/bin/contextveil setup from the project in a
real terminal; ordinary agent shell tools may not provide the required TTY.~/.local/bin/contextveil doctor from the project. For Codex, first trust the
hook on the Hooks need review screen or through /hooks.Installation alone is not proof of protection. Report every warn or fail line
from doctor.
Setup walks through:
Complete secret values are never displayed. Suggestions are only suggestions; you make the final choices. Rerun setup after changing a Known Source path override or when known host locations or fields change.
Use contextveil status to inspect your configuration. During normal use,
ContextVeil stays quiet unless it replaces something or encounters a problem.
.env entries, exact JSON fields, exact properties keys, and exact npmrc entries for each supported event instead of
keeping copied values.V1 supports Linux (including WSL on Windows) and macOS on x86_64 and arm64.
| Coding agent | Support | Text ContextVeil can replace | If ContextVeil fails |
|---|---|---|---|
| Claude Code | Production | String values in successful tool results that Claude allows hooks to replace | Claude continues with the original content: fail open |
| OpenAI Codex CLI | EXPERIMENTAL | Supported successful tool results; replacement becomes plain text and may lose structure | Codex continues with the original content: fail open |
| GitHub Copilot CLI | EXPERIMENTAL | Transformed user prompts and successful text tool results | Copilot continues with the original content: fail open |
| OpenCode | EXPERIMENTAL | New user text and successful standard tool output on the V1 plugin API | A detected problem stops that covered operation while the plugin is running |
Experimental integrations are functional and fixture-tested, but they are not part of the production support promise.
ContextVeil is a guardrail for accidental exposure, not a general security boundary:
LIM-023.${NAME} expressions literally; enroll the underlying
environment variable when npm substitutes the concrete credential.See limitations.md for the complete security boundary and coding-agent-specific gaps.
# find sources, record your choices, and install integrations. It is interactive and safe to rerun:
contextveil setup
# give a quick view of current sources and integrations:
contextveil status
# It can optionally offer a confirmed, paid/networked Claude test.
contextveil doctor
contextveil --help
contextveil --version
ContextVeil keeps source references in:
${XDG_CONFIG_HOME:-~/.config}/contextveil/config.toml for sources used across
projects;.contextveil.toml at the selected project root for project sources.The two files are additive. Review .contextveil.toml before using an untrusted
project: it can refer to environment variables or supported source files outside the
project. If a selected config is invalid or unreadable,
ContextVeil uses none of the sources for that event instead of applying partial redaction.
You can download a checksummed binary directly from
GitHub Releases, extract and place it
at ~/.local/bin/contextveil.
Alteratively, the install script detects your platform and architecture, downloads the matching release, verifies its SHA-256 checksum, and replaces the binary atomically:
install.sh [--install-dir DIR] [--version VERSION] [--allow-major-upgrade]
It never runs setup or changes ContextVeil or coding-agent configuration.
Rerunning it upgrades within the installed major version. A major-version upgrade
requires --allow-major-upgrade, and a prerelease is installed only when you name
its exact version.
To build the current source instead:
mise install
mise run build
The binary will be at target/release/contextveil.
mise is the supported entry point. It pins the Rust
toolchain, so no globally installed Rust utility is required. You still need a
system C linker: cc from build-essential on Linux or the Xcode command line
tools on macOS.
mise install # install the pinned toolchain
mise run check # formatting, Clippy with warnings denied, and tests
mise run build # release binary
mise run fuzz-smoke # bounded fuzz smoke run
mise run bench # representative runtime workload
mise run package # build and package a release artifact
mise run release-check
ContextVeil is free and open source under MIT OR Apache-2.0. It needs no account or hosted runtime.
99 commits
Rust
95.1%
Shell
3.0%
TypeScript
1.8%
Coding agents read environment variables, .env files, configuration, and command output that may contain credentials.
ContextVeil locally replaces the secret values you’ve chosen before supported text reaches the LLM — without blocking the workflow.
GITHUB_TOKEN=ghp_secret_example -> GITHUB_TOKEN=<SECRET:GITHUB_TOKEN>
The command still runs. The file still gets read. Only enrolled exact values are replaced; the rest of the output stays intact.
Install the latest stable release:
curl -fsSL https://raw.githubusercontent.com/daniel-sc/contextveil/v1.0.0/install.sh | bash
From your project directory, run:
~/.local/bin/contextveil setup
Review the suggested sources and select your coding-agent integration. Restart
the agent; in Codex, trust the hook on the Hooks need review screen or through
/hooks. Then run ~/.local/bin/contextveil doctor.
Setup requires a terminal and is safe to rerun. Add ~/.local/bin to your PATH
to use the shorter contextveil command.
Imagine asking a coding agent to debug your app. It reads .env or runs a command
such as printenv. Most of the output is useful, but it also contains an API key.
That key may become part of the next request to the model (LLM).
ContextVeil does not block the file read or command. The local operation still happens. On a supported harness integration path, ContextVeil changes the text headed to the model and leaves the rest useful:
DATABASE_URL=postgres://localhost/my_app
API_TOKEN=<SECRET:API_TOKEN>
LOG_LEVEL=debug
This is deliberately a small tool. It is not trying to recognize every possible secret or control everything an agent can do.
contextveil setup does the thoughtful part: it checks bounded known credential
files and probes maintained credential fields, alongside secret-like names and
credential-bearing URLs. These probes may suggest stale or non-secret strings.
New suggestions are automatically selected unless collisions are found; common
configuration literals are omitted. You can also add sources manually. Setup
shows only masked previews, lets you choose what to protect, and installs the
integrations you select. It does not scan arbitrary structured files or keys.
Daily use is boring on purpose: ContextVeil reads the current values, performs local exact-text replacement, and exits. There is no daemon, no network request, no account, no hosted service and no LLM deciding what looks secret. Clean events are silent.
And of course it is fast. You won't notice it, promise!
flowchart TD
subgraph setup [Setup: run once, rerun when needed]
direction LR
A[Find likely environment, .env, and Known Source entries]
B[You choose what to protect]
C[Install selected coding-agent integrations]
D[Store where values live, not the values]
A --> B --> C --> D
end
subgraph persistence [Persistence: configuration files]
direction LR
X[Global<br>~/.config/contextveil/config.toml]
Y[Project<br>.contextveil.toml]
X ~~~ Y
end
subgraph runtime [Runtime: for each supported event]
direction LR
E[Coding agent produces model-bound text]
F[Read current values from enrolled sources]
G{Exact value found?}
H[Pass text through unchanged]
I[Replace value with a placeholder]
J[Cleaned text continues to the LLM]
E --> F --> G
G -- No --> H --> J
G -- Yes --> I --> J
end
setup -. Stored in .-> persistence
persistence -. Used by .-> runtime
ContextVeil stores where to find each value, such as “the API_TOKEN environment
variable,” “the STRIPE_KEY entry in .env.local,” “the exact
/tokens/access_token field in auth.json,” or “the decoded
spring.datasource.password key in application.properties,” or “the exact
//registry.npmjs.org/:_authToken entry in .npmrc.” It does not copy
the value into its configuration. Changes to dotenv, JSON, properties, and npmrc files apply on the next supported
event. Environment changes apply after you restart the coding agent.
During setup, the following shared vocabulary identifies secret-like source names:
| Terms | Whole token | Compact suffix |
|---|---|---|
token, secret, password, passwd, passphrase, credential, credentials | Yes | Yes |
key | Yes | No |
apikey, accesskey, privatekey, clientsecret, authtoken, refreshtoken | No | Yes |
Matching is ASCII case-insensitive: Whole token means the term appears anywhere as a distinct part separated by _, -, ., spaces, or other non-ASCII-alphanumeric characters, such as DB_PASSWORD_PROD.
Compact suffix means those separators are removed and the resulting name ends with the term, such as StripeApiKey; plain key is excluded here to limit false positives.
Automatic suggestions currently cover:
.npmrc, using exact credential keys plus the same general name and URL checks.Across these rules, setup skips automatic suggestions whose
value are common literals, such as true, yes, on, 0,
enabled, null, nil, none, undefined, etc.
See the full Known Source Rule inventory for exact locations, fields, and exclusions.
Environment variables, dotenv files, JSON (including JSON5) files, exact Java properties keys, and exact npmrc keys can also be added manually without matching these automatic discovery rules.
Your agent may install ContextVeil, but source selection stays with you. Ask it to:
~/.local/bin.checksum verified, then run ~/.local/bin/contextveil --version.~/.local/bin/contextveil setup from the project in a
real terminal; ordinary agent shell tools may not provide the required TTY.~/.local/bin/contextveil doctor from the project. For Codex, first trust the
hook on the Hooks need review screen or through /hooks.Installation alone is not proof of protection. Report every warn or fail line
from doctor.
Setup walks through:
Complete secret values are never displayed. Suggestions are only suggestions; you make the final choices. Rerun setup after changing a Known Source path override or when known host locations or fields change.
Use contextveil status to inspect your configuration. During normal use,
ContextVeil stays quiet unless it replaces something or encounters a problem.
.env entries, exact JSON fields, exact properties keys, and exact npmrc entries for each supported event instead of
keeping copied values.V1 supports Linux (including WSL on Windows) and macOS on x86_64 and arm64.
| Coding agent | Support | Text ContextVeil can replace | If ContextVeil fails |
|---|---|---|---|
| Claude Code | Production | String values in successful tool results that Claude allows hooks to replace | Claude continues with the original content: fail open |
| OpenAI Codex CLI | EXPERIMENTAL | Supported successful tool results; replacement becomes plain text and may lose structure | Codex continues with the original content: fail open |
| GitHub Copilot CLI | EXPERIMENTAL | Transformed user prompts and successful text tool results | Copilot continues with the original content: fail open |
| OpenCode | EXPERIMENTAL | New user text and successful standard tool output on the V1 plugin API | A detected problem stops that covered operation while the plugin is running |
Experimental integrations are functional and fixture-tested, but they are not part of the production support promise.
ContextVeil is a guardrail for accidental exposure, not a general security boundary:
LIM-023.${NAME} expressions literally; enroll the underlying
environment variable when npm substitutes the concrete credential.See limitations.md for the complete security boundary and coding-agent-specific gaps.
# find sources, record your choices, and install integrations. It is interactive and safe to rerun:
contextveil setup
# give a quick view of current sources and integrations:
contextveil status
# It can optionally offer a confirmed, paid/networked Claude test.
contextveil doctor
contextveil --help
contextveil --version
ContextVeil keeps source references in:
${XDG_CONFIG_HOME:-~/.config}/contextveil/config.toml for sources used across
projects;.contextveil.toml at the selected project root for project sources.The two files are additive. Review .contextveil.toml before using an untrusted
project: it can refer to environment variables or supported source files outside the
project. If a selected config is invalid or unreadable,
ContextVeil uses none of the sources for that event instead of applying partial redaction.
You can download a checksummed binary directly from
GitHub Releases, extract and place it
at ~/.local/bin/contextveil.
Alteratively, the install script detects your platform and architecture, downloads the matching release, verifies its SHA-256 checksum, and replaces the binary atomically:
install.sh [--install-dir DIR] [--version VERSION] [--allow-major-upgrade]
It never runs setup or changes ContextVeil or coding-agent configuration.
Rerunning it upgrades within the installed major version. A major-version upgrade
requires --allow-major-upgrade, and a prerelease is installed only when you name
its exact version.
To build the current source instead:
mise install
mise run build
The binary will be at target/release/contextveil.
mise is the supported entry point. It pins the Rust
toolchain, so no globally installed Rust utility is required. You still need a
system C linker: cc from build-essential on Linux or the Xcode command line
tools on macOS.
mise install # install the pinned toolchain
mise run check # formatting, Clippy with warnings denied, and tests
mise run build # release binary
mise run fuzz-smoke # bounded fuzz smoke run
mise run bench # representative runtime workload
mise run package # build and package a release artifact
mise run release-check
ContextVeil is free and open source under MIT OR Apache-2.0. It needs no account or hosted runtime.
99 commits
Rust
95.1%
Shell
3.0%
TypeScript
1.8%