sink login, and every destructive command refuses to guess when there is no terminal to ask.
Credentials
SINK_API_KEY beats anything in the keychain or the config file, so it works on a runner that has never seen sink login. Store it in your CI provider’s own secret store — never in the repository.
Mint a dedicated key per pipeline under API Keys in the dashboard. Give it an expiry, and revoke it rather than rotating a shared one when a runner is retired.
.sink.json is committed, so the runner already knows which workspace, team, project and environment to use. Pass an environment name explicitly when a job targets a different one.Fetching secrets for a build
--force is what makes this safe to re-run: without it the command refuses to overwrite an existing .env and, with no terminal attached, fails rather than prompting.
To avoid writing a file at all:
Failing a build on drift
1 when the local file and the environment disagree, 0 when they match. Useful as a guard on a repo that keeps a checked-in .env.example, or as a post-deploy assertion that what shipped is what Sink holds.
Pushing from a pipeline
--yes is mandatory without a terminal — the command refuses to write otherwise. Add --dry-run first if you want the plan in the log before the run that applies it.
GitHub Actions
.github/workflows/deploy.yml
Pinning a version
Rate limits
Secret reads and writes are budgeted per credential at 120 requests a minute and 2,000 an hour. The CLI batches its work — one call to list, one bulk create, one bulk update — so a normal pull or push costs a handful of requests regardless of how many keys are involved. A job that loops one secret at a time is what runs into the ceiling. A429 carries Retry-After; wait it out rather than retrying immediately.