dumbtv
dumbtv가 ADB로 Fire TV에서 광고·추적·업데이트 알림을 제거, 루트·앱 변경 없이, 무료 오픈소스
프로덕션 AI 에이전트를 위한 자체 호스팅 정책 게이트, 기본 거부와 페이로드 승인 적용
Policy enforcement for teams running AI agents in production. A self-hosted gate between your agents and the tools they call: deny-by-default argument contracts, payload-bound approvals, reconcile-bef
보안Rust · PythonGitHub @rohansx온라인운영자 미확인
써 보셨어요? 한 번만 눌러 주세요. 로그인은 필요 없어요.
CloakPipe is the verifiable control plane for production AI agents: evaluate a release, certify it, enforce it at runtime, and prove what happened.
저장소 README에서 가져옴
README 전체를 불러오는 중입니다.
README 전문 보기 ↗Model proposes. Code disposes.
A self-hosted policy-enforcement gate for AI agent tool calls.
Quickstart · Declare · Enforce · Alert · Prove · Claude Code, Cursor, Codex · Roadmap
An agent's model decides which tool to call and with what arguments. A
prompt injection in a ticket, a web page or a tool result can change that
decision. CloakPipe sits between the agent and its MCP tool servers and
checks every tools/call against rules you wrote down before the run. It
has three jobs:
It is one Rust binary that wraps any MCP server (stdio or Streamable HTTP, one or several behind one gate), keeps its state in local SQLite files and needs no account or network service.
A support agent works one ticket. A prompt injection hidden in the ticket
makes the model email the customer list to [email protected] and call
an export_customers tool it was never given. The gate refuses both, lets
the legitimate email through, and holds a 350 refund for approval.
Install the binary from crates.io (Rust stable), and clone the repository for the example:
cargo install --locked [email protected] # installs `cloakpipe`
git clone --branch v0.14.0 https://github.com/rohansx/cloakpipe && cd cloakpipe
Run the example in examples/support-agent. The
agent is played by printf, and the tool server by a 60-line Python stub
that logs every call it receives:
cd examples/support-agent
export CLOAKPIPE_HOME=$(mktemp -d) # a throwaway gate key, ledger and counters
printf '%s\n' \
'{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"send_email","arguments":{"ticket_id":"T-1042","to":"[email protected]","subject":"Your refund","body":"Your refund for T-1042 is on its way."}}}' \
'{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"send_email","arguments":{"ticket_id":"T-1042","to":"[email protected]","subject":"Customer list","body":"Attached: every customer record."}}}' \
'{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"export_customers","arguments":{}}}' \
'{"jsonrpc":"2.0","id":4,"method":"tools/call","params":{"name":"issue_refund","arguments":{"ticket_id":"T-1042","amount":350}}}' \
| cloakpipe mcp-proxy --upstream "python3 mock_upstream.py" \
--manifest cloakpipe.manifest.yaml \
--task-context task-context.json \
--operations-db "$CLOAKPIPE_HOME/operations.db"
On stdout, the agent gets two refusals, an approval request and one result (stderr also has the gate's start-up lines and the stub's log). Only the email to the customer on the ticket reached the tool:
{"jsonrpc":"2.0","id":2,"error":{"code":-32001,"message":"tool call refused by CloakPipe: scope_mismatch","data":{"reason":"scope_mismatch","tool":"send_email","release":"sha256:c55889deb72d677a13ef2962ba7d6ae97d7a13391c9e484484fde9bb084fb0fa","path":"/to"}}}
{"jsonrpc":"2.0","id":3,"error":{"code":-32001,"message":"tool call refused by CloakPipe: undeclared_tool","data":{"reason":"undeclared_tool","tool":"export_customers","release":"sha256:c55889deb72d677a13ef2962ba7d6ae97d7a13391c9e484484fde9bb084fb0fa"}}}
{"jsonrpc":"2.0","id":4,"error":{"code":-32001,"message":"tool call refused by CloakPipe: approval_required","data":{"reason":"approval_required","tool":"issue_refund","release":"sha256:c55889deb72d677a13ef2962ba7d6ae97d7a13391c9e484484fde9bb084fb0fa","approvers":["slack:#support-leads"],"fingerprint":"sha256:5e2bb82dd5f59e1291041fa84e311a1d606c06d5e06710e9ef57a31838547aa6"}}}
upstream received: send_email {"body": "Your refund for T-1042 is on its way.", "subject": "Your refund", "ticket_id": "T-1042", "to": "[email protected]"}
{"jsonrpc":"2.0","id":1,"result":{"content":[{"type":"text","text":"send_email: done"}]}}
A refusal names the rule and the argument path, never the value. Each of
the four decisions, and the email's outcome (committed), is already an
entry in a signed ledger. Export it and verify it, as an auditor would:
cloakpipe ledger export --out audit-pack.tar
cloakpipe verify audit-pack.tar
entries: 5 (seq 0..4), chain OK, signatures OK
gaps: none
denials: 2, approvals: 1 required, 0 granted, unknown side effects: 0, reconciled: 0
manifests: sha256:c55889deb72d677a13ef2962ba7d6ae97d7a13391c9e484484fde9bb084fb0fa
result: OK
Next: approve the refund, watch the rate limit survive a restart, try shadow mode.
One file, cloakpipe.manifest.yaml, says which tools the agent may call and
what each call may carry. Anything it does not declare is refused. An
excerpt of the example's manifest:
release: support-agent
version: 2026.10.3
policy: ./policies/support.cedar
tools:
send_email:
args:
ticket_id: { type: string, one_of_context: ["ticket.id"], required: true }
to: { type: string, one_of_context: ["ticket.customer_email"], or_pattern: "@ourcompany\\.com$", required: true }
subject: { type: string, max_len: 200, required: true }
body: { type: string, max_len: 4000, required: true }
side_effect: true
idempotency_key: "{ticket_id}:{sha256(body)}"
issue_refund:
args:
ticket_id: { type: string, one_of_context: ["ticket.id"], required: true }
amount: { type: integer, min: 0, max: 500, required: true }
side_effect: true
approval:
when: "amount > 100"
approvers: ["slack:#support-leads"]
ttl: 15m
undeclared_tool; an
undeclared argument is undeclared_argument.one_of_context binds an argument to the trusted task context your
orchestrator writes (task-context.json), not to anything the model said.side_effect + idempotency_key make a call a tracked operation: a
retry is answered from the store and never runs twice, and a call whose
reply was lost is held as unknown until someone reconciles it.approval holds a call until a signed receipt for its exact
arguments exists; the refusal carries the routes and the call fingerprint
for whatever approval flow you run. show lists the arguments an
approver may see.The optional policy: file is Cedar, for
rules a per-argument contract cannot express: rate limits over persistent
counters, tiers, time windows. From the example:
@id("email-rate-limit")
forbid (principal, action == Action::"send_email", resource)
when { context.counters.send_email_1h >= 50 };
@id("refund-large")
@approval("slack:#support-leads")
permit (principal == Release::"support-agent", action == Action::"issue_refund", resource)
when { resource.args.amount > 100 && resource.args.amount <= 500 };
cloakpipe manifest validate checks both files and cloakpipe manifest hash
prints the digest every decision is bound to. Reference:
docs/MANIFEST.md, docs/POLICY.md and
the JSON Schema.
cloakpipe mcp-proxy --upstream "<server command>" --manifest <file> runs
the server as a child process and relays JSON-RPC both ways. Every
tools/call goes through, in order:
policy:): no permit or any matching
forbid is policy_denied, naming the forbids that decided it.approval.when or a Cedar
@approval permit, checked against receipts made with cloakpipe approve (or fetched from an approval broker) and the keys given with
--approver-key.The first stage that refuses wins, and an error in any stage refuses the
call as fail_closed. A refused call never reaches the tool. An allowed
call reaches it exactly as the agent sent it.
To try a new manifest on live traffic without blocking anything, run with
--mode shadow: every call is forwarded and the ledger records what enforce
mode would have decided. Contract and Cedar evaluation of the example's
calls takes about 0.05 ms at p99 in a release build (a CI test asserts p99
under 5 ms in a debug build); the ledger write, one SQLite insert, comes on
top.
PII pseudonymization is a separate, opt-in transform: --transform pii
replaces PII in allowed calls' arguments with tokens and puts the values
back in results. The manifest is always checked on the raw arguments. The
same regex engine also runs as an OpenAI- and Anthropic-compatible HTTP
proxy (cloakpipe start); see Other commands.
Details: docs/ACTION_BOUNDARY.md.
Either side of the gate can speak MCP's Streamable HTTP transport (spec
rev 2025-06-18) instead of stdio. Every tools/call gets the same
decision, refusal and ledger entry as over stdio.
Agents connect over HTTP with --listen:
cloakpipe mcp-proxy --listen 127.0.0.1:8900 \
--manifest examples/support-agent/cloakpipe.manifest.yaml \
--task-context examples/support-agent/task-context.json \
--operations-db ops.db \
--upstream "python3 examples/support-agent/mock_upstream.py"
# stderr: cloakpipe: MCP over HTTP listening on http://127.0.0.1:8900/mcp
claude mcp add --transport http support-tools http://127.0.0.1:8900/mcp
POST /mcp takes one JSON-RPC message and answers a request with one
application/json response (a notification gets 202). There are no
SSE response streams and no GET /mcp stream (405), so server-sent
notifications such as progress or tools/list_changed are not relayed
to HTTP agents.initialize issues an Mcp-Session-Id, which every later request must
carry (400 without one, 404 for an unknown one). DELETE /mcp ends
the session. All sessions share the one upstream; each request is
forwarded under a gate-unique id, so sessions never mix up replies, and
a notifications/cancelled only cancels a request of its own session.GET /health returns {"status":"ok","release":...,"release_digest":...}
and needs no token.Origin must be a loopback origin or the gate's own
(DNS rebinding). --listen-token-file FILE requires
Authorization: Bearer <token> on every /mcp request
(claude mcp add --transport http ... --header "Authorization: Bearer <token>").
The gate warns when it binds a non-loopback address; do that only with
a token.unknown, as over stdio.The upstream is an HTTP MCP server with --upstream-url (instead of
--upstream):
cloakpipe mcp-proxy --manifest cloakpipe.manifest.yaml \
--upstream-url https://tools.example.com/mcp \
--upstream-header "Authorization: env:TOOLS_AUTH"
The gate POSTs each message with the given headers (an env:VAR value is
read from the environment at start-up; values are never logged), accepts
JSON or SSE replies, and carries the server's Mcp-Session-Id and the
negotiated MCP-Protocol-Version. Upstream transport errors fail closed: a
connection error, an HTTP error status, or a reply that never comes answers
the agent with upstream_unavailable (JSON-RPC -32003), and a
side-effecting call that was sent becomes unknown in the operations store
and the ledger until reconciled. --listen and --upstream-url combine.
--upstream-url fronts one HTTP server; --server and --tools-lock
(below) take stdio servers, also behind --listen. HTTP servers behind
--server are on the roadmap.
One gate can front several MCP servers. Give each one as
--server NAME=COMMAND; --upstream is the server named default. The
gate starts and lists every server, answers the agent with one merged
tools/list, and routes each tools/call to the server that serves the
tool. A tool name two servers share stops the gate at start-up, unless the
manifest declares it per server as <server>__<tool>.
Pin the tool definitions you reviewed, and the gate hides and refuses
(tool_drift) any tool whose name, description, input schema or
annotations change afterwards:
cloakpipe tools pin --server 'mail=npx -y @acme/mail-mcp' --server 'files=...'
cloakpipe tools diff --lock cloakpipe.tools.lock --server 'mail=...' --server 'files=...'
cloakpipe mcp-proxy --manifest cloakpipe.manifest.yaml \
--server 'mail=...' --server 'files=...' --tools-lock cloakpipe.tools.lock
Even without a lock, a tool whose definition changes during a session is hidden and refused. All of this works the same for an agent over HTTP:
cloakpipe mcp-proxy --listen 127.0.0.1:8900 --listen-token-file listen.token \
--manifest cloakpipe.manifest.yaml \
--server 'mail=...' --server 'files=...' --tools-lock cloakpipe.tools.lock \
--webhook "$SLACK_WEBHOOK_URL" --webhook-format slack
A server that exits leaves the others serving: its open requests fail
closed (upstream_unavailable; a side-effecting call becomes unknown).
Details:
docs/ACTION_BOUNDARY.md.
cloakpipe approve signs a receipt by hand. To have a person approve from
Slack or a dashboard instead, point the gate at an approval broker:
cloakpipe mcp-proxy --manifest cloakpipe.manifest.yaml --upstream "python3 server.py" \
--task-context task-context.json --approvals approvals --approver-key approver.pub.json \
--approvals-url https://broker.example/v1/gates/$GATE_ID --approvals-secret-file gate.secret
A call refused as approval_required is filed with the broker in the
background (signed, with only the arguments the manifest's
approval.show lists), and the refusal tells the agent to retry after
approval. A poller fetches finished approvals, verifies each receipt
against --approver-key before writing it to --approvals, and the
retry runs. A denial is approval_denied; if the broker is down,
approvals simply do not arrive, and decisions never wait on it. The
protocol is open (two signed HTTP calls); CloakPipe Cloud implements it,
and so can your own service:
docs/APPROVALS.md.
Since v0.13.0. Each decision that needs attention
raises a gate event: decision.deny, approval.requested,
approval.mismatch, shadow.finding, side_effect.replayed,
side_effect.unknown, tool.drift or anchor.failed. An event carries the tool, the
reason, the contract path, the release, the ledger entry and a
deterministic fingerprint (the same failure always gets the same
fingerprint). It never carries an argument value.
cloakpipe mcp-proxy --manifest cloakpipe.manifest.yaml --upstream "python3 server.py" \
--events-log ~/.cloakpipe/events.jsonl \
--webhook "$SLACK_WEBHOOK_URL" --webhook-format slack \
--otel-endpoint http://localhost:4318
--webhook URL (repeatable) POSTs each event as JSON. Use
--webhook-format slack or discord for a chat message. With
--webhook-secret-file, each request is signed with
CloakPipe-Signature: t=<unix>,v1=hex(HMAC-SHA256(secret, "<t>.<body>")).--otel-endpoint exports one OpenTelemetry span per tool-call decision,
allows included, over OTLP/HTTP.--events-log appends every event as a line of JSON.cloakpipe events test --webhook URL --webhook-format slack sends a
sample event. cloakpipe events verify-signature checks a signature the
way a receiver should.Delivery runs on background threads with bounded queues: three tries, 5 s timeout, and drops are counted. A dead endpoint never delays a decision or changes it.
Details: docs/EVENTS.md.
cloakpipe.decision/v1 entry
with the tool, a keyed fingerprint of the arguments (never the values),
the decision and reason, the manifest and policy digests, the mode and the
side-effect outcome. Entries are hash-chained and each one is signed
(Ed25519) by the gate key. An entry is written before the call is
forwarded: if it cannot be written, the call is refused. The ledger is on
by default at ~/.cloakpipe/ledger.db.--anchor-every 500 --anchor-interval 10m seals entries
into numbered epochs on a background thread and anchors each epoch with an
RFC 3161 timestamp authority and Sigstore Rekor, so the operator cannot
back-date or rewrite history later without it showing.cloakpipe ledger export --out audit-pack.tar
writes one tar. cloakpipe verify audit-pack.tar --key <gate public key>
checks the chain, every signature, every epoch's timestamp token and Rekor
inclusion proof, and reports gaps, denials, approvals and unreconciled
side effects. It needs no network and no trust in the operator. The
standalone cloakpipe-verify binary does the same.Details: docs/ACTION_BOUNDARY.md, docs/ANCHORING.md, keys and rotation in docs/KEYS.md.
Each of these hosts starts MCP servers as commands. To put the gate in
front of a server, make cloakpipe mcp-proxy the command and move the real
server into --upstream. Use absolute paths, because the host decides the
working directory.
The snippets below wrap the reference filesystem server with
examples/filesystem: a read-only manifest whose
Cedar policy also refuses .env and key files. Replace /path/to/... with
your own paths.
Claude Code (claude mcp add; --scope project writes .mcp.json,
and Claude Code asks you to approve a project server the first time):
claude mcp add project-files --scope project -- cloakpipe mcp-proxy \
--manifest /path/to/cloakpipe/examples/filesystem/cloakpipe.manifest.yaml \
--upstream "npx -y @modelcontextprotocol/server-filesystem /path/to/project"
Or run the gate as an HTTP server and point Claude Code at its URL (the gate can then serve several agents, and needs no per-host command):
cloakpipe mcp-proxy --listen 127.0.0.1:8900 --listen-token-file ~/.cloakpipe/listen.token \
--manifest /path/to/cloakpipe/examples/filesystem/cloakpipe.manifest.yaml \
--upstream "npx -y @modelcontextprotocol/server-filesystem /path/to/project"
claude mcp add --transport http project-files http://127.0.0.1:8900/mcp \
--header "Authorization: Bearer $(cat ~/.cloakpipe/listen.token)"
or write .mcp.json yourself (Cursor reads the same shape from
.cursor/mcp.json in the project, or ~/.cursor/mcp.json):
{
"mcpServers": {
"project-files": {
"command": "cloakpipe",
"args": [
"mcp-proxy",
"--manifest", "/path/to/cloakpipe/examples/filesystem/cloakpipe.manifest.yaml",
"--upstream", "npx -y @modelcontextprotocol/server-filesystem /path/to/project"
]
}
}
}
Codex (~/.codex/config.toml):
[mcp_servers.project-files]
command = "cloakpipe"
args = ["mcp-proxy", "--manifest", "/path/to/cloakpipe/examples/filesystem/cloakpipe.manifest.yaml", "--upstream", "npx -y @modelcontextprotocol/server-filesystem /path/to/project"]
What to know:
--tools-lock): it is left out of the
list and refused as tool_drift.one_of_context there, or pass
--task-context <file>.env as usual; the server inherits them through the gate.~/.cloakpipe/ledger.db, signed with
~/.cloakpipe/gate.key. Run cloakpipe ledger entries to see them.The full threat model, including what the evidence does and does not prove, is in docs/THREAT_MODEL.md.
Shipping in this repository (developer preview; formats may still change before 1.0)
v0.13.0 (28 October 2026):
mcp-proxy --listen serves agents over Streamable HTTP
and --upstream-url fronts an HTTP MCP server
(MCP over HTTP)--server NAME=COMMAND, merged tools/list, per-tool routing), tools/list
pinning (cloakpipe tools pin|diff, --tools-lock) and drift detection
(tool_drift, tool.drift events)
(Several servers)v0.14.0 (29 October 2026):
--approvals-url, approval.show,
approval_denied, cloakpipe approvals keys): an open protocol,
verified receipts only (docs/APPROVALS.md)Next
GET /mcp stream for
HTTP agents--server and --tools-lock (today these take
stdio servers; --upstream-url fronts one HTTP server)Later, not started
| Topic | Where |
|---|---|
| Manifest format | docs/MANIFEST.md, JSON Schema |
| Cedar policies, entities, counters | docs/POLICY.md |
| Contracts, approvals, operations, the decision ledger | docs/ACTION_BOUNDARY.md |
| Approvals through a broker: setup and the open protocol | docs/APPROVALS.md |
| Anchoring and offline verification | docs/ANCHORING.md |
| Keys: gate, approvers, anchoring roots, rotation | docs/KEYS.md |
| Threat model | docs/THREAT_MODEL.md |
| Examples | support-agent (the quickstart), filesystem, action-boundary (legacy manifest format) |
| Legacy: certification, release audit packs, the 2025 proxy design | docs/legacy/ |
cargo install --locked [email protected] installs cloakpipe from
crates.io, and cargo install --locked [email protected] the
standalone verifier. From a checkout, use --path crates/cloakpipe-cli
(or crates/cloakpipe-verify) instead.
The default binary is the lean gate: mcp-proxy and its evidence tooling,
plus regex PII detection. Everything else is a cargo feature, off by
default:
| Feature | Adds |
|---|---|
ner | ONNX Runtime and GLiNER-PII NER detectors for the PII transform and proxy |
rag | the tree and vector subcommands and the proxy's /v1/embeddings and /tree/* routes |
certification | Legacy: the evaluation import, certification and release audit pack commands (docs/legacy/). The certification gate in mcp-proxy is opt-in: it applies only when a certification flag (--certification, --trust, ...) is given; otherwise the manifest alone decides |
full | All of the above |
cargo install --path crates/cloakpipe-cli --locked --features ner
The image runs the gate over HTTP by default. Its entrypoint
(docker/gate-entrypoint.sh) builds the
mcp-proxy flags from CLOAKPIPE_* variables:
docker build -t cloakpipe-gate .
openssl rand -hex 32 > listen.token
docker run --rm -p 127.0.0.1:8900:8900 \
-v "$PWD/cloakpipe.manifest.yaml:/app/cloakpipe.manifest.yaml:ro" \
-v "$PWD/listen.token:/run/secrets/listen.token:ro" \
-v cloakpipe-data:/data \
-e CLOAKPIPE_UPSTREAM_URL=https://tools.example.com/mcp \
-e CLOAKPIPE_LISTEN_TOKEN_FILE=/run/secrets/listen.token \
cloakpipe-gate
| Variable | Becomes |
|---|---|
CLOAKPIPE_UPSTREAM_URL or CLOAKPIPE_UPSTREAM (one is required) | --upstream-url (an HTTP MCP server) or --upstream (a command inside the container) |
CLOAKPIPE_UPSTREAM_HEADER | one --upstream-header (Name: value, the value may be env:VAR) |
CLOAKPIPE_MANIFEST (default /app/cloakpipe.manifest.yaml) | --manifest; mount yours there |
CLOAKPIPE_LISTEN (default 0.0.0.0:8900) | --listen |
CLOAKPIPE_LISTEN_TOKEN_FILE | --listen-token-file; required on a non-loopback address unless CLOAKPIPE_INSECURE_NO_TOKEN=1 |
CLOAKPIPE_TOOLS_LOCK | --tools-lock (with CLOAKPIPE_UPSTREAM) |
CLOAKPIPE_WEBHOOK_URL, CLOAKPIPE_WEBHOOK_SECRET_FILE, CLOAKPIPE_WEBHOOK_FORMAT | --webhook, --webhook-secret-file, --webhook-format |
CLOAKPIPE_OTEL_ENDPOINT, CLOAKPIPE_EVENTS_LOG | --otel-endpoint, --events-log |
Arguments after gate are added to the flags (docker run ... cloakpipe-gate gate --mode shadow). The decision ledger, the gate key and the operations
store live on the /data volume (CLOAKPIPE_HOME=/data); the health check
asks GET /health. docker/compose.example.yaml
runs the gate in front of the support-agent example's tools over HTTP.
Any other command runs cloakpipe itself: docker run -p 8900:8900 -e OPENAI_API_KEY=... cloakpipe-gate start is the PII proxy with the bundled
config, as the root docker-compose.yml does.
| Command | Purpose |
|---|---|
cloakpipe approve | Sign an approval receipt for one exact call |
cloakpipe approvals keys | Fetch an approval broker's approver public keys as --approver-key files |
cloakpipe action fingerprint | Print the fingerprint of a call |
cloakpipe operations list / reconcile | Inspect side-effecting calls; settle an unknown one |
cloakpipe ledger entries / public-key / export | Read the decision ledger, print the gate key, write an audit pack |
cloakpipe release keygen | Make an Ed25519 key file (approver keys, a gate key you manage yourself) |
cloakpipe start | The regex PII proxy for OpenAI- and Anthropic-compatible APIs (writes cloakpipe.toml on first run) |
cloakpipe test --text "..." | Show what PII detection finds in a string |
cloakpipe scan | Mask PII in .txt/.md/.json/.csv files |
cloakpipe mcp | An MCP server exposing the PII tools (pseudonymize, rehydrate, detect, ...) |
LangChain and LlamaIndex wrappers for the PII proxy live in
integrations/; they do not gate tool calls.
| Crate | Responsibility |
|---|---|
cloakpipe-cli | The cloakpipe binary. |
cloakpipe-mcp | The MCP gate: relay, decision order, approvals, operations store, ledger writes, anchoring thread. |
cloakpipe-release | Manifests (v1 and legacy), tool contracts, the approval condition language, call fingerprints. |
cloakpipe-policy | Cedar evaluation and the persistent call counters. |
cloakpipe-receipt | DSSE envelopes and signed approval receipts. |
cloakpipe-ledger | The decision ledger, epochs, the gate key, audit pack export. |
cloakpipe-anchor | RFC 3161 and Rekor clients, Merkle batching. |
cloakpipe-verify | The standalone offline verifier; depends on no evidence producer. |
cloakpipe-core | PII detection, pseudonymization, encrypted vault. |
See CONTRIBUTING.md. In short:
cargo test --workspace
cargo clippy --workspace --all-targets -- -D warnings
cargo build -p cloakpipe-cli -p cloakpipe-verify && python3 tools/check_docs.py --bin target/debug
The last line checks that every command in this README and in docs/
exists, and runs the quickstart above. Please report vulnerabilities
privately; see SECURITY.md.
MIT © 2026 Rohan Sharma.
| Release history | CHANGELOG.md |
cloakpipe-proxy| The LLM HTTP proxy (PII). |
cloakpipe-audit | JSONL/SQLite audit log for the HTTP proxy. |
cloakpipe-cert | Legacy certification (certification feature). |
cloakpipe-tree, cloakpipe-vector | Optional RAG tooling (rag feature). |
cloakleak, cloakleak-cli | A PII-leak benchmark run as a CI gate for the PII transform. |
cloakpipe-local | Placeholder; not implemented. |