Skip to main content
Version: MVP

Secrets

5 min readFor everyoneUpdated 2026-05-19

What you'll learn

  • Where Craik stores secret material and what it never persists.
  • The redaction guarantee that applies to every receipt, handoff, and log.
  • How policy profiles and capability grants compose with redaction.
  • How to extend redaction for project-specific patterns.

Design rationale: ADR 0003 · Secret handling.

Secrets are runtime-tier data

Craik treats secrets as sensitive runtime material — not as configuration. They live in a single, narrow directory; they never leak into receipts, case files, or handoffs in raw form; and the redaction guard runs on every persistence path regardless of profile.

Where secrets live

Path
Scope
Purpose
~/.craik/secrets/
default
Per-user secret material when CRAIK_HOME is unset.
$CRAIK_HOME/secrets/
override
When CRAIK_HOME is set, secrets live under that home.

The secrets directory is created with owner-only permissions wherever the platform supports it (POSIX 0700, restricted ACLs on Windows). Craik never creates project-local .craik/secrets/ directories inside repositories — that would silently widen the secret surface area to anything in the repo's filesystem.

What Craik never persists as raw secrets

The redaction guard ensures the following payloads carry redacted summaries instead of raw secret material:

Receipts

Provider call receipts, credential-use receipts, side-effect receipts — all pass through redaction before storage.

Handoffs

Structured handoffs and their Markdown renderings — both are scrubbed before persistence.

Logs

Diagnostic logs are scrubbed of bearer tokens, auth URLs, and configured secret patterns.

Case files

Case files carry references to credentials by profile URI — never by secret value.

Memory proposals

Proposal payloads are scrubbed; structured fields with secret-like names are explicitly redacted.

The redaction guard

The central redaction utility is craik.runtime.policy.redaction. It redacts several categories of input before any persistence path completes:

  1. Bearer tokens. Authorization: Bearer …, Authorization: Basic …, and similar HTTP header shapes.

  2. Common key/value secret shapes. Pattern-matched secrets like AWS_SECRET_ACCESS_KEY=…, OPENAI_API_KEY=sk-…, password=….

  3. Auth URLs. URLs with credential material in the query string or userinfo (https://user:pass@host/…, https://host/?token=…).

  4. Configured secret patterns. Project-specific regexes the operator has declared as sensitive.

  5. Structured fields with secret-like names. Fields named secret, token, password, api_key, etc., regardless of their value's shape.

The legacy import path craik.runtime.redaction remains available for backward compatibility — both refer to the same guard.

Policy and grants do not override redaction

This is a hard rule:

Policy profiles

The trusted-local fail-open profile still requires redacted receipts. There is no profile that permits raw secret persistence.

Capability grants

A capability grant authorizes an action — it does not authorize storing unredacted secrets even when the action is allowed.

Fail-open paths

A fail-open run produces a receipt. The receipt is still scrubbed.

Automation runs

Automation enforces fail-closed defaults; redaction runs on top of that, not instead of it.

How to handle a real credential

The canonical pattern:

Reference a credential by env-var name, not value
craik auth add anthropic:work \
--kind=api-key \
--env-var=ANTHROPIC_API_KEY

Craik stores the reference (--env-var=ANTHROPIC_API_KEY) in config/. The actual secret stays in the operator's environment, secret manager, or local-CLI credential file. When a run needs the credential, the runtime resolves it at call time, uses it, and never writes the raw value anywhere.

For local-CLI OAuth flows, secret-manager references, Stigmem-backed credentials, and workload-identity patterns, see Authentication and credentials.

Extending redaction

If your project has secrets that don't match the built-in patterns — internal API tokens with a custom prefix, signed URLs with non-standard query parameters — extend the redaction guard:

craik policy show

Inspect the active policy envelope's redaction patterns before extending.

See Redaction reference for the configuration shape and validation rules.

A practical checklist

  1. Never commit ~/.craik/secrets/ or $CRAIK_HOME/secrets/. They're local-only by design.

  2. Reference credentials by env-var or profile URI. Pass the name, not the value, to craik auth add.

  3. Run craik doctor before live calls. It reports which credential profiles resolve cleanly and which are degraded.

  4. Audit receipts periodically. craik receipts list and inspect a sample — if anything looks like a raw secret slipped through, file an incident immediately.

  5. Treat the redaction guard as load-bearing. Don't disable rules, don't add catch-alls, and don't route receipts around it.

What's next