npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

sync-cf-secrets

v0.6.0

Published

Sync Cloudflare Workers secrets from 1Password or Bitwarden. Push, pull, and diff secrets across environments.

Downloads

140

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-secrets

Requires Node.js 20+ and wrangler installed.

A bundled Claude Code skill is available — run sync-cf-secrets install-skill to let AI assistants help manage your secrets.

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 local

Commands

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_ME placeholders

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-run

copy <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.

Use --fields to copy specific fields only — this merges into the existing target item instead of replacing it:

sync-cf-secrets copy local staging
sync-cf-secrets copy staging production
sync-cf-secrets copy staging production --fields GOOGLE_CLIENT_ID,GOOGLE_CLIENT_SECRET

push <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 pushing

pull <env>

Generate a .dev.vars file from your password manager.

sync-cf-secrets pull local

list <env>

List secret names deployed to a Cloudflare Workers environment.

sync-cf-secrets list staging

diff <env>

Compare secrets in your password manager vs what's deployed to Cloudflare.

sync-cf-secrets diff production --verbose

Options

| Flag | Description | |---|---| | --provider <name> | Password manager: 1password, bitwarden (auto-detected by default) | | --vault <name> | Override vault name | | --fields <a,b,...> | Only copy specific fields (for copy command) | | --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_TOKEN is set, then op CLI, then bw CLI)
  • vault — project name from package.json
  • prefix — same as vault
  • wranglerConfig — auto-searches for wrangler.toml, wrangler.jsonc, or wrangler.json (including apps/web/)
  • devVarsPath.dev.vars next to your wrangler config
  • environments — auto-discovered from your wrangler config's env block, plus local

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

A Claude Code skill is bundled with this package. It teaches AI assistants the full command reference and workflow patterns so they can help manage your secrets — for example, asking Claude to "copy staging secrets to production" will run the right command.

To install it:

sync-cf-secrets install-skill

This copies the skill to ~/.claude/skills/sync-cf-secrets/. Claude Code picks it up automatically from there.

To see where the bundled skill file lives (e.g. to copy it to a different tool's skill directory):

sync-cf-secrets reveal-skill

Contributing

This project uses changesets for version management and OIDC trusted publishing for npm publish. The actual publish only ever runs from GitHub Actions, triggered by a vX.Y.Z tag push, and npm stamps the released package with a provenance attestation.

# After making changes, create a changeset and commit it alongside the change
pnpm changeset
# → interactive prompt: pick patch/minor/major, write a summary

# When ready to release
pnpm release
# → guards (clean tree, on main, up-to-date, pending changeset),
#   runs typecheck/test/build, bumps package.json + CHANGELOG.md,
#   commits as "Version X.Y.Z", shows you the diff, and prompts before
#   pushing main + the vX.Y.Z tag. Tag push triggers
#   .github/workflows/release.yml, which publishes to npm via OIDC.

If the release workflow fails after the tag is pushed

The Version X.Y.Z commit is on main and the vX.Y.Z tag is pushed, but nothing has been published to npm. Because pnpm release has already consumed the pending changeset, you cannot rerun pnpm release to retry — it will fail the "no pending changesets" guard.

Recovery:

# 1. Delete the bad tag locally and on the remote
git tag -d vX.Y.Z
git push origin :refs/tags/vX.Y.Z

# 2. Fix whatever broke, commit the fix on main, push
git commit -am "fix: ..."
git push origin main

# 3. Re-tag HEAD (annotated, matching how changesets creates them) and
#    push the tag to re-trigger the release workflow
git tag -a vX.Y.Z -m "Version X.Y.Z"
git push origin vX.Y.Z

See CLAUDE.md for the full architecture and release notes.

Security

  • 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.vars files include a "do not commit" warning
  • Duplicate items are detected and cleaned up by unique ID

License

MIT