The CLI in CI/CD
Inject vault secrets into any process with env pull, push, and run, using ONECLAW_TOKEN and ONECLAW_VAULT_ID in CI.
In a pipeline you don't want secrets committed to a repo or pasted into CI settings one by one. The CLI pulls them from a vault at runtime and injects them into your process.
In CI, authenticate with env vars instead of 1claw login: set ONECLAW_TOKEN (a JWT) or ONECLAW_API_KEY, plus ONECLAW_VAULT_ID for the vault to read.
- 1
Set the non-interactive credentials in your shell or CI secrets store. Exchange your 1ck_ key at POST /v1/auth/api-key-token (see Foundations), or use your 1ck_ key directly as ONECLAW_API_KEY. Use the vault UUID from
1claw vault listor from the Foundations track.bashexport ONECLAW_TOKEN="your-jwt" export ONECLAW_VAULT_ID="your-vault-uuid" - 2
Seed your vault with a local .env file first.
bash1claw env push .env - 3
Pull secrets into a .env file for tooling that reads one.
bash1claw env pull -o .env.production - 4
Or skip the file entirely and run a command with secrets injected as env vars. This is the safest option since nothing lands on disk.
bash1claw env run -- npm start
CLI env commands (env push, env pull, env run) require @1claw/cli v0.38+. If you see errors on v0.37.x, use the API directly: curl -X PUT https://api.1claw.co/v1/vaults/$ONECLAW_VAULT_ID/secrets/config/env -H "Authorization: Bearer $ONECLAW_TOKEN" -H "Content-Type: application/json" -d '{"type":"env_bundle","value":"KEY=value\nKEY2=value2"}'
- name: Deploy with secrets
env:
ONECLAW_TOKEN: ${{ secrets.ONECLAW_TOKEN }}
ONECLAW_VAULT_ID: ${{ secrets.ONECLAW_VAULT_ID }}
run: |
npx @1claw/cli env run -- npm run deployFor offline or flaky-network builds, run 1claw env cache to store secrets in a local AES-256-GCM encrypted file (default TTL 300s). env run uses a valid cache automatically; add --no-cache to bypass it.
Your build process now starts with secrets injected straight from the vault, with no plaintext secrets checked into the repo or pasted into CI config.
Where this goes wrong in practice. CI is the place secrets leak most often, because a pipeline is a machine that prints things for a living.
- Values reach the log. Any step that echoes an environment, runs with set -x, or dumps a failed request body publishes the secret to anyone who can read the build. The official GitHub Action emits ::add-mask:: before export for exactly this reason.
- Pull requests from forks inherit the workflow. A deny-by-default ref list is what stops an untrusted branch from running a job that can read your vault.
- One CI credential is shared by every job. Convenient, and it means the smallest job on the least trusted branch holds the same access as the deploy.
- The key is stored in CI and forgotten. A key in a CI secret store is a key with no expiry in a system many people can configure, which is why the agent key should be exchanged for a short-lived token at job start rather than used directly.
- Caches and artifacts outlive the job. A .env written for a build step and left in a cached directory is available to every subsequent run.
Assume the build log is public even when the repository is private. Logs get pasted into issues, forwarded to vendors and attached to support tickets more often than anyone plans for.
Decide
A workflow needs one secret during a deploy step. A colleague adds it to the job-level env block so any step can use it, arguing that scoping it per step is fussy.
What is the practical objection?
Check your understanding
3 questionsWhich command runs a process with vault secrets injected as env vars and nothing written to disk?
Which two env vars typically authenticate and scope the CLI in CI?
What does 1claw env cache store secrets in?