sync-cf-secrets 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +18 -0
- package/package.json +10 -3
- package/scripts/postinstall.js +27 -0
- package/skill/SKILL.md +176 -0
package/README.md
CHANGED
|
@@ -172,6 +172,24 @@ interface SecretProvider {
|
|
|
172
172
|
}
|
|
173
173
|
```
|
|
174
174
|
|
|
175
|
+
## AI Skill
|
|
176
|
+
|
|
177
|
+
Installing this package automatically registers a [Claude Code skill](https://docs.anthropic.com/en/docs/claude-code) at `~/.claude/skills/sync-cf-secrets/`. This teaches AI assistants the full command reference and workflow patterns so they can help manage your secrets.
|
|
178
|
+
|
|
179
|
+
## Contributing
|
|
180
|
+
|
|
181
|
+
This project uses [changesets](https://github.com/changesets/changesets) for version management.
|
|
182
|
+
|
|
183
|
+
```bash
|
|
184
|
+
# After making changes, create a changeset
|
|
185
|
+
npm run changeset
|
|
186
|
+
# → interactive prompt: pick patch/minor/major, write a summary
|
|
187
|
+
|
|
188
|
+
# When ready to release
|
|
189
|
+
npm run version # bumps package.json version, updates CHANGELOG.md
|
|
190
|
+
npm run release # builds and publishes to npm
|
|
191
|
+
```
|
|
192
|
+
|
|
175
193
|
## Security
|
|
176
194
|
|
|
177
195
|
- Secret values are piped to wrangler via stdin — never exposed in CLI arguments or process listings
|
package/package.json
CHANGED
|
@@ -1,18 +1,24 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sync-cf-secrets",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Sync Cloudflare Workers secrets from 1Password or Bitwarden. Push, pull, and diff secrets across environments.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"sync-cf-secrets": "./dist/cli.js"
|
|
8
8
|
},
|
|
9
9
|
"files": [
|
|
10
|
-
"dist"
|
|
10
|
+
"dist",
|
|
11
|
+
"skill",
|
|
12
|
+
"scripts/postinstall.js"
|
|
11
13
|
],
|
|
12
14
|
"scripts": {
|
|
13
15
|
"build": "tsc",
|
|
14
16
|
"dev": "tsc --watch",
|
|
15
|
-
"
|
|
17
|
+
"postinstall": "node scripts/postinstall.js",
|
|
18
|
+
"prepublishOnly": "tsc",
|
|
19
|
+
"changeset": "changeset",
|
|
20
|
+
"version": "changeset version",
|
|
21
|
+
"release": "npm run build && changeset publish"
|
|
16
22
|
},
|
|
17
23
|
"keywords": [
|
|
18
24
|
"cloudflare",
|
|
@@ -46,6 +52,7 @@
|
|
|
46
52
|
}
|
|
47
53
|
},
|
|
48
54
|
"devDependencies": {
|
|
55
|
+
"@changesets/cli": "^2.30.0",
|
|
49
56
|
"@types/node": "^25.5.2",
|
|
50
57
|
"typescript": "^5.7.0"
|
|
51
58
|
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// Copies the skill file to ~/.claude/skills/sync-cf-secrets/
|
|
4
|
+
// so Claude Code auto-discovers it.
|
|
5
|
+
|
|
6
|
+
import { existsSync, mkdirSync, copyFileSync } from "node:fs";
|
|
7
|
+
import { join, dirname } from "node:path";
|
|
8
|
+
import { homedir } from "node:os";
|
|
9
|
+
import { fileURLToPath } from "node:url";
|
|
10
|
+
|
|
11
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
12
|
+
const skillSource = join(__dirname, "..", "skill", "SKILL.md");
|
|
13
|
+
const skillTarget = join(homedir(), ".claude", "skills", "sync-cf-secrets", "SKILL.md");
|
|
14
|
+
|
|
15
|
+
try {
|
|
16
|
+
if (!existsSync(skillSource)) {
|
|
17
|
+
// Silently skip if skill file not found (e.g. in CI)
|
|
18
|
+
process.exit(0);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const targetDir = dirname(skillTarget);
|
|
22
|
+
mkdirSync(targetDir, { recursive: true });
|
|
23
|
+
copyFileSync(skillSource, skillTarget);
|
|
24
|
+
console.log("sync-cf-secrets: Installed Claude Code skill");
|
|
25
|
+
} catch {
|
|
26
|
+
// Don't fail the install if skill copy fails
|
|
27
|
+
}
|
package/skill/SKILL.md
ADDED
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: sync-cf-secrets
|
|
3
|
+
version: 0.1.0
|
|
4
|
+
description: Sync Cloudflare Workers secrets from a password manager (1Password, Bitwarden). Use when the user asks about managing, pushing, pulling, or diffing Cloudflare secrets, or setting up environment variables for Cloudflare Workers.
|
|
5
|
+
requires:
|
|
6
|
+
bins: ["sync-cf-secrets"]
|
|
7
|
+
auth: true
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# Cloudflare Secrets Manager
|
|
11
|
+
|
|
12
|
+
Help users manage Cloudflare Workers secrets using the `sync-cf-secrets` CLI, which syncs secrets between a password manager (1Password or Bitwarden) and Cloudflare Workers environments.
|
|
13
|
+
|
|
14
|
+
## Agent Guidance
|
|
15
|
+
|
|
16
|
+
### Key Principles
|
|
17
|
+
|
|
18
|
+
- **Always use `--dry-run` first** — preview any destructive operation before committing
|
|
19
|
+
- **Never log or display secret values** — only show field names
|
|
20
|
+
- **Confirm before `init` or `copy`** — these delete and recreate password manager items
|
|
21
|
+
- **The password manager is the source of truth** — Cloudflare is the deployment target; Cloudflare does not expose secret values
|
|
22
|
+
- **Wrangler vars are excluded automatically** — variables defined as `vars` in the wrangler config are non-secret config; `init`, `copy`, and `push` skip them
|
|
23
|
+
|
|
24
|
+
### Design Principles
|
|
25
|
+
|
|
26
|
+
- Auto-discovers environments from the wrangler config (`wrangler.toml` / `wrangler.jsonc`)
|
|
27
|
+
- Auto-detects the password manager CLI (`op` for 1Password, `bw` for Bitwarden)
|
|
28
|
+
- Config is optional — sensible defaults from `package.json` and wrangler config
|
|
29
|
+
- Secret values are piped via stdin to wrangler, never exposed in CLI arguments
|
|
30
|
+
|
|
31
|
+
### Safety Rules
|
|
32
|
+
|
|
33
|
+
- Always use `--dry-run` before `push`, `init`, or `copy` to preview changes
|
|
34
|
+
- Never run `init` without the user confirming they want to replace existing items
|
|
35
|
+
- Never display secret values in output — only field names
|
|
36
|
+
- Verify the correct vault and environment before pushing
|
|
37
|
+
|
|
38
|
+
### Workflow Patterns
|
|
39
|
+
|
|
40
|
+
#### First-time Setup
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
# 1. Create password manager items from existing .dev.vars
|
|
44
|
+
sync-cf-secrets init --dry-run # preview first
|
|
45
|
+
sync-cf-secrets init
|
|
46
|
+
|
|
47
|
+
# 2. Copy local values to staging (most are the same)
|
|
48
|
+
sync-cf-secrets copy local staging
|
|
49
|
+
|
|
50
|
+
# 3. User edits staging item in password manager (change AUTH_SECRET, etc.)
|
|
51
|
+
|
|
52
|
+
# 4. Push to Cloudflare
|
|
53
|
+
sync-cf-secrets push staging --dry-run
|
|
54
|
+
sync-cf-secrets push staging
|
|
55
|
+
|
|
56
|
+
# 5. Repeat for production
|
|
57
|
+
sync-cf-secrets copy staging production
|
|
58
|
+
# User edits production item (swap test keys for live keys)
|
|
59
|
+
sync-cf-secrets push production
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
#### Onboarding a New Developer
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
# Pull local dev secrets from the shared password manager vault
|
|
66
|
+
sync-cf-secrets pull local
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
#### Adding a New Secret
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
# 1. Add the field to the password manager item(s) manually
|
|
73
|
+
# 2. Push the updated secrets
|
|
74
|
+
sync-cf-secrets push staging
|
|
75
|
+
sync-cf-secrets push production
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
#### Auditing After a Deployment
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
sync-cf-secrets diff staging
|
|
82
|
+
sync-cf-secrets diff production
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## Command Reference
|
|
88
|
+
|
|
89
|
+
### `init`
|
|
90
|
+
|
|
91
|
+
Create password manager items for all environments discovered from the wrangler config. Reads field names and values from `.dev.vars`. The `local` item gets actual values; other environments get `CHANGE_ME` placeholders. Excludes wrangler `vars`. Prompts before replacing existing items.
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
sync-cf-secrets init
|
|
95
|
+
sync-cf-secrets init --dry-run
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### `copy <from> <to>`
|
|
99
|
+
|
|
100
|
+
Copy secrets from one environment's password manager item to another. Excludes wrangler `vars` for the target environment. Prompts before replacing the target.
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
sync-cf-secrets copy local staging
|
|
104
|
+
sync-cf-secrets copy staging production
|
|
105
|
+
sync-cf-secrets copy local staging --dry-run
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### `push <env>`
|
|
109
|
+
|
|
110
|
+
Push secrets from the password manager to Cloudflare via `wrangler secret put`. Skips wrangler `vars`. Reports progress per secret and continues on individual failures.
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
sync-cf-secrets push staging
|
|
114
|
+
sync-cf-secrets push production
|
|
115
|
+
sync-cf-secrets push staging --dry-run
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### `pull <env>`
|
|
119
|
+
|
|
120
|
+
Fetch secrets from the password manager and write a `.dev.vars` file.
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
sync-cf-secrets pull local
|
|
124
|
+
sync-cf-secrets pull staging --dry-run
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### `list <env>`
|
|
128
|
+
|
|
129
|
+
List secret names deployed to a Cloudflare Workers environment. Values are never exposed.
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
sync-cf-secrets list staging
|
|
133
|
+
sync-cf-secrets list production
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
### `diff <env>`
|
|
137
|
+
|
|
138
|
+
Compare secret names in the password manager vs what's deployed to Cloudflare. Shows missing, extra, and matching secrets.
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
sync-cf-secrets diff staging
|
|
142
|
+
sync-cf-secrets diff production --verbose
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
### Global Options
|
|
146
|
+
|
|
147
|
+
| Option | Description |
|
|
148
|
+
|---|---|
|
|
149
|
+
| `--provider <name>` | Force a provider: `1password`, `bitwarden` |
|
|
150
|
+
| `--vault <name>` | Override the vault name |
|
|
151
|
+
| `--dry-run` | Preview without making changes |
|
|
152
|
+
| `--verbose` | Show more detail |
|
|
153
|
+
|
|
154
|
+
---
|
|
155
|
+
|
|
156
|
+
## Configuration
|
|
157
|
+
|
|
158
|
+
Optional `.sync-cf-secrets.json` in project root:
|
|
159
|
+
|
|
160
|
+
```json
|
|
161
|
+
{
|
|
162
|
+
"provider": "1password",
|
|
163
|
+
"vault": "myproject",
|
|
164
|
+
"prefix": "myproject",
|
|
165
|
+
"wranglerConfig": "apps/web/wrangler.jsonc",
|
|
166
|
+
"devVarsPath": "apps/web/.dev.vars"
|
|
167
|
+
}
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
All fields have defaults: `provider` auto-detected, `vault`/`prefix` from `package.json` name, `wranglerConfig` auto-searched, `devVarsPath` next to wrangler config, environments auto-discovered from wrangler config `env` block.
|
|
171
|
+
|
|
172
|
+
## Prerequisites
|
|
173
|
+
|
|
174
|
+
- **1Password**: `op` CLI installed, authenticated via the desktop app (biometric)
|
|
175
|
+
- **Bitwarden**: `bw` CLI installed, `bw login` + `export BW_SESSION=$(bw unlock --raw)`
|
|
176
|
+
- `wrangler` installed (for `push`, `list`, `diff` commands)
|