Package Exports
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (sync-cf-secrets) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
sync-cf-secrets
Sync secrets from your password manager to Cloudflare Workers. Supports 1Password and Bitwarden with a pluggable provider architecture.
Why
Managing Cloudflare Workers secrets is tedious — tokens from third parties are often single-use, so they end up in your password manager, then need to be manually pushed via wrangler secret put for each environment. This tool automates that.
Install
npm install -g sync-cf-secrets
# or as a devDependency
npm install -D sync-cf-secretsRequires Node.js 18.3+ and wrangler installed.
Quick Start
# 1. Bootstrap: create password manager items for all environments
sync-cf-secrets init
# 2. Copy local secrets to staging (most values are the same)
sync-cf-secrets copy local staging
# 3. Edit staging item in your password manager — change any values that differ
# 4. Push secrets to Cloudflare
sync-cf-secrets push staging
# 5. Generate .dev.vars for local dev from password manager
sync-cf-secrets pull localCommands
init
Create password manager items for all environments discovered from your wrangler config. Reads field names and values from .dev.vars:
- local item gets the actual values from
.dev.vars - staging, production, etc. get the same fields with
CHANGE_MEplaceholders
Any variables already defined as vars in your wrangler config are automatically excluded — they're non-secret config and don't belong in the password manager.
If items already exist, you'll be prompted before they're replaced.
sync-cf-secrets init
sync-cf-secrets init --dry-runcopy <from> <to>
Copy secrets from one environment's password manager item to another. Useful when environments share most values (e.g. local and staging both use test/sandbox API keys).
Variables defined as vars in the target environment's wrangler config are excluded.
sync-cf-secrets copy local staging
sync-cf-secrets copy staging productionpush <env>
Push secrets from your password manager to a Cloudflare Workers environment.
Variables already defined as vars in your wrangler config are automatically skipped.
sync-cf-secrets push staging
sync-cf-secrets push production --dry-run # preview without pushingpull <env>
Generate a .dev.vars file from your password manager.
sync-cf-secrets pull locallist <env>
List secret names deployed to a Cloudflare Workers environment.
sync-cf-secrets list stagingdiff <env>
Compare secrets in your password manager vs what's deployed to Cloudflare.
sync-cf-secrets diff production --verboseOptions
| Flag | Description |
|---|---|
--provider <name> |
Password manager: 1password, bitwarden (auto-detected by default) |
--vault <name> |
Override vault name |
--dry-run |
Show what would happen without doing it |
--verbose |
Show more detail |
--help |
Show help |
Wrangler Vars vs Secrets
The tool automatically reads your wrangler config (wrangler.toml / wrangler.jsonc) and excludes any names defined as vars. These are non-secret environment config (like DEPLOY_ENV or AUTH_URL) that Cloudflare manages as plaintext bindings — pushing them as secrets would cause a "Binding name already in use" error.
This filtering is per-environment, so a variable that's a var in staging but not in production is handled correctly.
Configuration
Create a .sync-cf-secrets.json in your project root (all fields optional):
{
"provider": "1password",
"vault": "Engineering",
"prefix": "myproject",
"wranglerConfig": "apps/web/wrangler.jsonc",
"devVarsPath": "apps/web/.dev.vars",
"environments": {
"local": { "item": "myproject local" },
"staging": { "item": "myproject staging" },
"production": { "item": "myproject production" }
}
}Defaults
- provider — auto-detected (prefers 1Password SDK when
OP_SERVICE_ACCOUNT_TOKENis set, thenopCLI, thenbwCLI) - vault — project name from
package.json - prefix — same as vault
- wranglerConfig — auto-searches for
wrangler.toml,wrangler.jsonc, orwrangler.json(includingapps/web/) - devVarsPath —
.dev.varsnext to your wrangler config - environments — auto-discovered from your wrangler config's
envblock, pluslocal
Password Manager Setup
1Password
The easiest way to get started is sync-cf-secrets init, which creates Secure Note items with the right fields. You can also create them manually — one Secure Note per environment with custom fields where the label is the env var name and the value is the secret.
Two backends are available:
1. JavaScript SDK (recommended for CI/AI agents): When OP_SERVICE_ACCOUNT_TOKEN is set, the tool uses the @1password/sdk package directly — no CLI binary needed. This works in sandboxed environments (Claude Code, CI containers, etc.) where the op CLI can't run.
export OP_SERVICE_ACCOUNT_TOKEN="ops_..."Create a service account with read/write access to the vault. Service accounts can only access custom vaults (not Personal/Private).
2. CLI (op): For interactive use with biometric/Touch ID auth via the 1Password desktop app. Requires op CLI version 2.18.0+. Used automatically when no service account token is set.
Bitwarden
Same concept — one Secure Note per environment with custom fields for each secret.
Requires the Bitwarden CLI (bw).
Adding a Provider
Providers implement the SecretProvider interface:
interface SecretProvider {
name: string;
cli: string;
validate(): Promise<void>;
exists(opts: { vault: string; item: string }): Promise<boolean>;
fetch(opts: { vault: string; item: string }): Promise<Map<string, string>>;
save(opts: { vault: string; item: string; secrets: Map<string, string> }): Promise<void>;
listFields(opts: { vault: string; item: string }): Promise<string[]>;
}AI Skill
Installing this package automatically registers a Claude Code skill at ~/.claude/skills/sync-cf-secrets/. This teaches AI assistants the full command reference and workflow patterns so they can help manage your secrets.
Contributing
This project uses changesets for version management.
# After making changes, create a changeset
pnpm run changeset
# → interactive prompt: pick patch/minor/major, write a summary
# When ready to release
pnpm run version # bumps package.json version, updates CHANGELOG.md
pnpm run release # builds and publishes to npmSecurity
- Secret values are piped to wrangler via stdin — never exposed in CLI arguments or process listings
- No intermediate temp files
- Requires password manager authentication (biometrics/master password)
- Generated
.dev.varsfiles include a "do not commit" warning - Duplicate items are detected and cleaned up by unique ID
License
MIT